jordan.terrell
Just trying to make sense of things...

State Machine ViewModel

Friday, 19 March 2010 08:09 by jordan.terrell

Jason Bock recently wrote a post on turning WPF Binding errors into exceptions.  When I first started to get into WPF development, I too found that the binding system was significantly better (i.e. actually worked) that Microsoft’s previous attempts to do UI binding.  That said, I also found, as Jason did, that WPF’s binding system was less than helpful when you fat-fingered a binding.  I did learn that there we many ways that you could get debugging output from the binding system, but I never took it to the level that Jason did and turned the binding errors into exceptions.  I’m sure I’ll find his binding extension useful in the future.

Sometimes Invisible Binding Errors are Okay

However, I did make a comment on Jason’s post that later on I found a use for not having exceptions be thrown on data binding issues errors.  There is a pattern that I’ve used on one or two WPF applications where I host a collection of “screens”, which are just UserControls, in a single Window, and the visibility of the UserControls is driven by the DataContext of the Window.  The DataContext is both a ViewModel in the Model-View-ViewModel pattern, and an implementation of the State pattern.

The difference is that, in a traditional State pattern implementation, you typically have a base class or interface that defines all of the input or operations that all the states need to respond to.  However, with a state-based ViewModel and WPFs dynamic binding system you will see this is not necessary.

Let’s start with a simple scenario, a wizard-like, step-by-step WPF application for taking simple feedback comments from users.  Let’s say the list of states is: AskForComment, CaptureName, CaptureEmail, CaptureText, and Thanks.  Clicking the next button will transition from one state to the next, changing the DataContext of the Window to the new state.  As the state changes, the WPF binding system will be notified of this.  It will attempt to rebind the visibility of all the UserControls to the new DataContext, which is the new state, and depending on the state, different UserControls will be visible.  The UserControls that are not visible, will have binding errors, but since they are not visible and thus not in use, the errors can be ignored.  The user can happily enter information into the newly visible control, unaware of any errors.

I’ve created a sample application that shows one way this could be implemented. If you look at the MainWindow.xaml, you will see five UserControls that represent the different views as the states change.  Each of them has their Visibility property bound to the current state through a StateVisibilityConverter.  Inside each UserControl, various elements are bound to properties on the DataContext that may or may not exists, depending on what state you are in – but again, that doesn’t matter – if the properties don’t exist, the UserControl should not be visible.

The key takeaway is that sometimes you can use the lack of exceptions on WPF binding errors to your advantage, and I would venture a guess that Microsoft decided not to throw exceptions on binding errors to enable scenarios like this.

Comments are closed