One of my biggest goals with this application is achieving a complete understanding of how the MVVM pattern can be applied and how to achieve strong code coverage through unit tests. Thus far the first portion of the goal is proceeding nicely, regrettably I am having difficultly with the second piece.
One of the nice thing I am finding is by using an Dependency Injection model for class type resolution I can greatly cut down on the amount of code on my code behinds. I was already familiar with this aspect with respect to properties and using INotifyPropertyChanged but now I am finally getting a chance to apply it to commands. For example, I defined the following interface to define the contract which a view model must follow for the Venue management screen:
What this gives me is a way to implement multiple view models and allow them to operate on the same or different views. This achieves a very nice, clean separation between the view model code and the view itself.
One of the neat things that WPF can allow you to do is to bind to commands. This removes the need for the view to specify an event handler and allows the event to be directly routed to the view model where it can be handled. I created two classes which implement this interface: EventCommand and ActivatedEventCommand. This is how I perform the binding in code and XAML:
The only real difference between EventCommand and ActivatedCommand is that the activated variant will update its Enabled status based on the return value of the provided lambda. This is curcial because once the binding here it functions like any other property, with one slight twist. Whenever the property changes ICommand.CanExecute is polled. If the method returns false, then the command will be disabled.
What this means is whenever I notify that SaveCommand has changed WPF will set IsEnabled to the boolean return value of ICommand.CanExecute. This allows the interface to update the enabled state of components automatically based on the internal state of the view model. A very powerful concept, especially when you then combine it with ElementBinding.
Now, not only does the Save button automatically disable itself when saving is not allowed, it is being watched by other elements within the form who will set their IsEnabled state based on whether the Save button is enabled. Through adding almost no code, I am quickly able to provide a clean intuitive interface which switches state intelligently. This is the code is my code behind:
Since we define each ViewModel as a Singleton, thereby allowing only one instance to event exist we don’t even need to worry about casting or accessing the LayoutRoot property here. However, I wonder what will happen if I hit my “Back” button and do not reset the internal state of the view model. Could be kind of weird when I come back to this page later on. But Ill check that out later.
The MVVM pattern is a very powerful pattern and requires much discipline and understanding to fully implement. This is why it is common for programmers to rely on a framework like Caliburn.Micro to do this for them. That said, I have often found that understanding what you are doing makes using a framework much easier. I can already see some of the concepts I didn’t quite grasp in Caliburn making more and more sense to me. With any luck when I do finally decide to transition this application to use Caliburn the switch will be very easy.
Command Binding is quickly becoming one of my new favorite aspects in WPF, though it does seem you can command bind everything, case in point the SelectionChanged event on the DataGrid. But, it does make things significantly cleaner. I am also certain that when I focus more on the testing aspect of this it will be easier to test with all the view logic in the View Model instead of the code behind.