Using MvvmLight with (XAML) Silverligtht 4 or WPF
Introduction
This tutorial will try and explain the advantages and the 'how to' of using MVVMLight within your XAML application. So that you can produce code that easier mantainable and more importantly testable.
Why Use The MVVM Pattern
The tight coupling of GUI to code behind has over the years meant that testing the code-behind can be some what tricky. In that how do you mimic the selected event in the GUI to call the binded event code - you can mimic teh call to your event code but how do you get the selected item from the combo (in the GUI) that doesn't exist, as you are not running the GUI but testing the methods that the GUI uses.
What was needed was a loose coupling between the GUI and the code behind, this is where Context classes come in - XAML (Silverlight or WPF) have a concept where a Silverlight page can have a (context) class associated with it for it's events and also (more importantly) have setters and getters associated with the bindings to gui controls. So that, when a property is updated by it's setter - a call to your 'NotifyPropertyChanged' method in the class 'INotifyPropertyChanged' will trigger the rebinding to the control.
Install And Integrating MVVMLight Into Your Project
You can download and follow the instructions from Gala's web site here http://www.galasoft.ch/mvvm/getstarted/
OR
- Get NUGet (which is a handy plugin for Visual Studio - http://nuget.codeplex.com/releases) to convert your application into a MVVMLight application.
- How to integret NUGet into VS2010-> http://nuget.codeplex.com/wikipage?title=Using%20the%20Extension%20Manager%20to%20Install%20the%20Library%20Package%20Manager%20(NuGet)
- How to add MVVMLight dlls to your project.
http://nuget.codeplex.com/wikipage?title=Finding%20and%20Installing%20a%20Package%20Using%20the%20Add%20Library%20Package%20Reference%20Dialog%20Box (in this tutorial search for MVVMLight) - Use this tutorial as a guide to adding the dll's to your project
http://insomniacgeek.com/nuget-packages-for-mvvm-light/
Below is how to convert you project to an MVVMLight project after installing NUGet and running the MVVMLight installer.
Binding Scenarios
Commands
A command is basically a reference point for when an event happens in the GUI. The respective command (set in the xaml) will be triggered, in any the MVVM design pattern, there is a RelyCommand that will determine if the command's associated method can be executed. Below you can see that the button's command property has been bound to the 'ButtonCommand' command in code, in the context class - thus wiring up a (button click) event to this command in code - which in turn will call a method to act upon the command.
Passing a Parameter to a Command
It is possible using a reference to 'System.Windows.Interactivity' class to pass parameters to the called command (again there is a RelyCommand for this type of passing). Below the trigger is the 'SelectionChanged' event of the textbox, which will call the 'LstBoxChangedCommand' command with the parameter of the contents of the textbox.
RelyCommand (inc. passing back parameter)
The RelyCommand will determine if the associated method of the command can be executed. There are a couple overrides for the RelyCommand, in that you can call the RelyCommand without a parameter, or with. Basically, there are two methods that can be called for each version (parameter or not). The only difference (other that expecting a parameter) is that you can fire a 'canExecute' method to determine if the command is valid to proceed processing. There is also a relycommand method that does not take a 'canExecute' and it will always fire the associated method of the command. For example, you might want the SelectedItemChanged event of a ComboBox to always fire, as you do not depend on any other controls\scenairos on the page. In the two images below you can see the object browser view on the MVVMLight RelayCommand methods - the first one does not take parameters, but the second image shows the signiture of the Relaycommand that does take a parameter.
Binding Setter Properties in XAML
To associate a binding with a setter property in the context class (that will be two way so that the changes can be posted back to the control - one way only means that the control tells the property that it has changed.). In the image below you can see that the 'SelectedItem' is bound to the property 'SelectedTemplate' - which is a reference to a class in a observablecollection.
MVVM NotifyPropertyChanged Method
With the above binding, and in two way mode, I can make a chage to the property (maybe in the method associated with a command, for example, I have selected an item from a combobox - this triggers a command, the method associated with that command then sets a property that is bound to a label - that label with the use of the 'NotifyPropertyChanged' method will post the update back to the label.
Binding Events properties in XAML
A developer will want to bind many gui control events back to commands in the context class. This is possible using the 'System.Windows.Interactivity' class. [Code Snippet] We can bind any event in the comboxbox (for example) back to a command in the context class - to get say the selected item in the combobox, we would generally pass a parameter to the command, as there is a caverat here, in that the SelectionChanged event is triggered before the SelectedItem binding can take place - so in this case we would pass the selectedItem to the command. Knowning that this scenairo can happen, but also knowning that we can get around this can only extend the use of MVVM design pattern. Basically, no event cannot be triggered to a command in another class and actioned upon. Looking at this image again you can see that I am binding to an event in the textbox - 'SelectionChanged'. You can now bind to any event that a control has.
Raising Seperate Cmmand to Execute (within another command method)
The situation will arise that you need another event\command to fire after you have changed a property or to a seperate event - this is possible to by using the the 'RaiseCanExecuteChanged' method on the respective command that you wish to evaluate.
Sample Application
Download MvvmLightSilverlight.zip - 1.4 MB This application will need the MvvmLight dll's added (as they made the size of the project after zipping over 11mb - if you following the instructions in the introduction using NUGet - you can add the dll's easily).
The sample code, basically validates what the user types in (the textbox) against the combobox to enable or disable the button (a valid entry is something that is not already in the combobox.