technology from back to front

Archive for January, 2010

Validating whole forms with WPF Data Binding

Microsoft WPF includes a data binding framework that provides a simple declarative mechanism to associate and validate data with UI components – read some good tips and tricks here.

This works well very well for simple form validation but sometimes you may want to perform a more complex series of validations and reflect the failures back to the user in a similar manner to the field level validation. For example, a particular combination of fields may result in breaking a business rule for that particular user and the client has asked you to highlight all of these fields with a similar message. In this situation additional validation when the form is submitted may be the simplest solution, so we need to carry out some process like this:

  1. Perform validation of business object obtained from data binding.
  2. Interpret validation results.
  3. Flag multiple fields as being incorrect.

To perform the last step you need to know how to programmatically force binding errors. I googled and binged for ages trying to find this information so here is the simple recipe.

  1. Make sure the fields that the fields that need to show binding errors have a mode of TwoWay or OneWayToSource in their binding expression.
  2. Make sure the fields that need to show binding errors have the ValidatesOnDataErrors set to true in their binding expressions.
  3. Force the validation errors when the form is submitted like this
ValidationError validationError = new ValidationError(emptyValidationRule,
         textBox.GetBindingExpression(TextBox.TextProperty), "Error message", null);
Validation.MarkInvalid(textBox.GetBindingExpression(TextBox.TextProperty), validationError);

I am using an emptyValidationRule just to satisfy the type signature here. It is never actually used because my business validation is carried out elsewhere. The emptyValidationRule is a simple implementation of a ValidationRule that always fails.

To remove a validation error from a field

Validation.ClearInvalid(textBox.GetBindingExpression(TextBox.TextProperty));

This approach can also help if you need to validate that a ComboBox value is actually selected when no default value has been provided. Validation rules only fire automatically if data binding actually occurs, that means the ComboBox must actually be used. You could force databinding to occur like this:

comboBox.GetBindingExpression(ComboBox.SelectedItemProperty).UpdateTarget();

when the ComboBox loses focus. However, if the user just uses the mouse to press the form submit button, the combobox will never gain or lose focus so no validation will take place. To work around this you can validate in the way I have shown above or perform UpdateTarget operations on all of the ComboBox controls in the form when submit is pressed.

by
tim
on
31/01/10

Silicon Roundabout

Wired have been updating their map of Silicon Roundabout.
Find us and our friends and neighbours.

The Silicon Roundabout was first described in July 2008 by Matt Biddulph (then CTO of Dopplr, now at Nokia).

Wired UK have since been maintaining a list of the tech companies that cluster around Old Street. LShift is pleased to be nearing it’s tenth year in the area. Note also presence of Rabbit, our partners and office mates.

by
Administrator
on
29/01/10

Plugin exchange types for RabbitMQ

An obvious extension point for an AMQP broker is the addition of new types of exchange. An exchange type essentially represents an algorithm for dispatching messages to queues, usually based on the message’s routing key, given how the queues are bound to the exchange — it’s a message routing algorithm.

At a minimum, supporting new exchange types requires only some scaffolding to plug in to (an exchange type registry) and a hook for routing messages. However, this wouldn’t support some more interesting use cases, and in particular it didn’t support our [motivating use case](http://oceanobservatories.org/spaces/download/attachments/19432960/ooi-amqp-api-20091228.pdf?version=1). Exchange types that want to keep their own state need to be initialised, and be notified about other lifecycle events.
Read more…

by
mikeb
on
22/01/10

Upgrading your disk with LVM

I’ve just had my most pleasant move from a smaller to a larger disk ever thanks to LVM, with vastly reduced downtime, and I thought I’d share my happy experience. Read more…

by
Paul Crowley
on
15/01/10

Network server programming with SML/NJ and CML

My experience with [SML/NJ](http://www.smlnj.org/) has been almost uniformly positive, over the years. We used it extensively in a previous project to write a compiler (targeting the .NET CLR) for a pi-calculus-based language, and it was fantastic. One drawback with it, though, is the lack of documentation. Finding out how to (a) compile for and (b) use [CML](http://cml.cs.uchicago.edu/) takes real stamina. I’ve only just now, after several hours poring over webpages, mailing lists, and library source code, gotten to the point where I have a running socket server.

## Download source code, building, and running

The following example is comprised of a `.cm` file for building the program, and the `.sml` file itself. The complete sources:

* [`test.cm`][cm]
* [`test.sml`][sml]

[cm]: http://dev.lshift.net/tonyg/test.cm
[sml]: http://dev.lshift.net/tonyg/test.sml

Running the following command compiles the project:

ml-build test.cm Testprog.main

The `ml-build` output is a heap file, with a file extension dependent on your architecture and operating system. For me, right now, it produces `test.x86-darwin`. To run the program:

sml @SMLload=test.x86-darwin

substituting the name of your `ml-build`-produced heap file as necessary.

On Ubuntu, you will need to have run `apt-get install smlnj libcml-smlnj libcmlutil-smlnj` to ensure both SML/NJ and CML are present on your system.

## The build control file

The [`test.cm`][cm] file contains

Group is
$cml/basis.cm
$cml/cml.cm
$cml-lib/smlnj-lib.cm
test.sml

which instructs the build system to use the CML variants of the basis and the standard SML/NJ library, as well as the core CML library itself and the source code of our program. For more information about the SML CM build control system, see [here](http://www.smlnj.org/doc/CM/index.html).

## The example source code

Turning to [`test.sml`][sml] now, we first declare the ML structure (module) we’ll be constructing. The structure name is also part of one of the command-line arguments to `ml-build` above, telling it which function to use as the main function for the program.

structure Testprog = struct

Next, we bring the contents of the `TextIO` module into scope. This is necessary in order to use the `print` function with CML; if we use the standard version of `print`, the output is unreliable. The special CML variant is needed. We also declare a local alias `SU` for the global `SockUtil` structure.

open TextIO
structure SU = SockUtil

ML programs end up being written upside down, in a sense, because function definitions need to precede their use (unless mutually-recursive definitions are used). For this reason, the next chunk is `connMain`, the function called in a new lightweight thread when an inbound TCP connection has been accepted. Here, it simply prints out a countdown from 10 over the course of the next five seconds or so, before closing the socket. Multiple connections end up running connMain in independent threads of control, leading automatically to the natural and obvious interleaving of outputs on concurrent connections.

fun connMain s =
let fun count 0 = SU.sendStr (s, “Bye!\r\n”)
| count n = (SU.sendStr (s, “Hello ” ^ (Int.toString n) ^ “\r\n”);
CML.sync (CML.timeOutEvt (Time.fromReal 0.5));
count (n – 1))
in
count 10;
print “Closing the connection.\n”;
Socket.close s
end

The function that depends on `connMain` is the accept loop, which repeatedly accepts a connection and spawns a connection thread for it.

fun acceptLoop server_sock =
let val (s, _) = Socket.accept server_sock
in
print “Accepted a connection.\n”;
CML.spawn (fn () => connMain(s));
acceptLoop server_sock
end

The next function is the primordial CML thread, responsible for creating the TCP server socket and entering the accept loop. We set `SO_REUSEADDR` on the socket, listen on port 8989 with a connection backlog of 5, and enter the accept loop.

fun cml_main (program_name, arglist) =
let val s = INetSock.TCP.socket()
in
Socket.Ctl.setREUSEADDR (s, true);
Socket.bind(s, INetSock.any 8989);
Socket.listen(s, 5);
print “Entering accept loop…\n”;
acceptLoop s
end

Finally, the function we told `ml-build` to use as the main entry point of the program. The only thing we do here is disable SIGPIPE (otherwise we get rudely killed if a remote client’s socket closes!) and start CML’s scheduler running with a primordial thread function. When the scheduler decides that everything is over and the program is complete, it returns control to us. (The lone `end` closes the `struct` definition way back at the top of the file.)

fun main (program_name, arglist) =
(UnixSignals.setHandler (UnixSignals.sigPIPE, UnixSignals.IGNORE);
RunCML.doit (fn () => cml_main(program_name, arglist), NONE);
OS.Process.success)

end

by
tonyg
on
01/01/10

Search

Categories

You are currently browsing the LShift Ltd. blog archives for January, 2010.

Feeds

Archives

2000-14 LShift Ltd, 1st Floor, Hoxton Point, 6 Rufus Street, London, N1 6PE, UK+44 (0)20 7729 7060   Contact us