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:
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.
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
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:
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.
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.
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.
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…
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:
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:
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
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.
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))
print “Closing the connection.\n”;
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
print “Accepted a connection.\n”;
CML.spawn (fn () => connMain(s));
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()
Socket.Ctl.setREUSEADDR (s, true);
Socket.bind(s, INetSock.any 8989);
print “Entering accept loop…\n”;
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);
You are currently browsing the LShift Ltd. blog archives for January, 2010.