Getting Started w/ Windows 8, MVVM Light and EventToCommand
Now that Windows 8 and Visual Studio are in RTM I wanted to put together a quick entry for those Windows Phone developers making the transition to Windows 8 development with their MVVM Light skills.
Laurent Bugnion, is the creator of the MVVM Light toolkit and I, as well as many others, have been using this for Windows Phone development for a while now. I am porting on of my applications to Windows 8 and wanted to take the knowledge of this toolkit to the new platform hoping that there were either some new enhancements and/or not many changes so that I could just go. Well that was the deal.
MVVM Light Toolkit for Windows 8 RTM
The latest installer for the toolkit, "MVVM Light Toolkit V4 RTM", is available from CodePlex. According to Laurent's blog it is a side by side install with previous versions:> MVVM Light for Windows 8 is a side-by-side install with the standard MVVM Light V3 or V4 beta. Simply download and run the MSI from Codeplex. As usual, the last step of the installation performs a “/setup” of Visual Studio to actualize the project template cache, and unfortunately this last step can last very long. Please be patient and don’t cancel before the end! The installation process is very similar to that described on the MVVM Light installation page (except that there is no NuGet installer for VS11 yet).The following link states the summary of the ported components from the previous versions, but I'll paraphrase here:
- ObservableObject including all ways to raise PropertyChanged.
- ViewModelBase including all ways to raise PropertyChanged.
- Messenger including all message types except DialogMessage (see below).
- RelayCommand with and without parameter.
- SimpleIoc which might well be the very first IOC container working on Windows 8. Man do I love the SimpleIoc! Makes adding the new views soooo much easier than in the Windows Phone version.There are a few missing components, one of which is EventToCommand, however thanks to a new friend I have made, Joost van Schaik (see his blog here), there is a solution to that and it's available as a nuget package with some additional behavior features I encourage you to look into but I'll at least cover the EventToCommand features he offers.Getting StartedMVVM Light Project TemplateAfter installing the toolkit you will see that there is a new project template available in the Visual Studio 2012 New Project DialogNoted as "Windows Metro Style"Name the project "MvvmLight_Walkthrough" and click Ok.The project template is simple, but add some new features that were not in previous versions of the toolkit. In the Solution Explorer you'll notice a Design folder with a class called DesignDataService. This is a great feature; the default template putting in a design data class repository.Second, as in the past version of the toolkit there is the normal ViewModelLocator class, but in this version there is new feature - SimpleIoc, a container class which if you are like me had everything else in a container for DI with the exception of the ViewModels unless you rolled your own.public class ViewModelLocator { static ViewModelLocator() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); if (ViewModelBase.IsInDesignModeStatic) { SimpleIoc.Default.Register<idataservice, design.designdataservice="">(); } else { SimpleIoc.Default.Register<idataservice, dataservice="">(); } SimpleIoc.Default.Register(); } /// /// Gets the Main property. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "This non-static member is needed for data binding purposes.")] public MainViewModel Main { get { return ServiceLocator.Current.GetInstance(); } } /// /// Cleans up all the resources. /// public static void Cleanup() { }And last, in the Model folder, Laurent has been kind enough to also include an IDataService interface and DataService class to show in the example how to use the real time and design time data models. These are all wired up in the ViewModelLocator as show above.Now if we simply run the application you should get the following to make sure it's all good to go!Running in the SimulatorAs you may or may not notice, this is not to dis-similar from the previous project template test from the previous version.MainViewModelThe binding of the ViewModel to the View is the same as it was in the previous model and there are no noticeable changes to the ViewModelTemplate. On thing to note is that all options for RaisePropertyChanged are included in this release where as in the previous version you would have to get the "Pre-release" version from nuget in order to use them. For example, the built in template puts in the following:/// /// The property's name. /// public const string WelcomeTitlePropertyName = "WelcomeTitle"; private string _welcomeTitle = string.Empty; /// /// Gets the WelcomeTitle property. /// Changes to that property's value raise the PropertyChanged event. /// public string WelcomeTitle { get { return _welcomeTitle; } set { if (_welcomeTitle == value) { return; } _welcomeTitle = value; RaisePropertyChanged(WelcomeTitlePropertyName); } }Noticeably where RaisePropertyChanged is using a string value, one of the options now available in the release is to remove the WelcomeTitlePropertyName variable and then changeRaisePropertyChanged(WelcomeTitlePropertyName);to RaisePropertyChanged(() => WelcomeTitle);</idataservice,></idataservice,>The other nice benefit here is that the template has also put in the wiring for injecting the IDataService into the constructor for the ViewModel. Some of these little thing we developers either take for granted that someone has gone through the trouble of putting the plumbing in there or call it the boring work that has to be done before we get the real work done. You can easily put other dependencies in the constructor here and then just add the mappings in the constructor of the ViewModelLocator by simply registering the types with the SimpleIoc container.public MainViewModel(IDataService dataService) { _dataService = dataService; _dataService.GetData( (item, error) => { if (error != null) { // Report error here return; } WelcomeTitle = item.Title; }); }Now What?.A simple example here is to add some content to the MainPage and see how we navigate to a second view. I won't bore you with the details of adding in the controls to the page but here's what the page should look like when you're done.
Added a little MvvmLight color for fun
EventToCommand
Now lets just add a prompt to the submit button. But wait, what where's my EventToCommand??? Sure with the button there is a Command property and you can set that to an ICommand in the ViewModel and everything is happy. But, there are plenty of controls, both baked into WinRT and third party controls that do not have that property. So, for simplicity sake I'm using this control and will get the EventToCommand back in your toolbox, or your Joostbox I should say.
Off to Nuget!
I had this issue where I was looking for the behaviors when porting an app I was working on and could find the dang behaviors in Blend so I went to nuget and did some searching and there wasn't anything that was shaking my fancy. Then I came across Joost van Schaik (see his blog here) and his WinRTBehaviors library and just so happens I hit him in the middle of uploading the nuget package for Win8nl.Now this is a package of Behaviors that was originally a Windows Phone 7 library and It's now growing in its own direction and now contains some Windows 8 specific stuff (according to nuget). So let's get it installed real quick.Install the package by typing the following into the Nuget Package Manager Console or searching for Win8nl in the package explorer.> PM> Install-Package Win8nl
It will add the library and the necessary dependencies to the project, which include WinRTBehaviors. For more information on the other behaviors there check out Joost's blog.Adding EventToCommand First, lets add the references to the XAML page:
xmlns:WinRtBehaviors="using:WinRtBehaviors"
xmlns:Win8nl_Behavior="using:Win8nl.Behaviors"
Next, locate the button control and add the following inside the button XAML: <button x:name="btnSubmit" content="Submit" ="" ="" fontfamily="{StaticResource MyFont}" fontsize="{StaticResource MyFontSize}" horizontalalignment="Center" margin="0,20,0,0"> winrtbehaviors:interaction.behaviors <win8nl_behavior:eventtocommandbehavior event="Tapped" ="" command="AreYouSureCommand" ="" commandparameter="{Binding MyName}"> </win8nl_behavior:eventtocommandbehavior></winrtbehaviors:interaction.behaviors> Now, open the MainViewModel.cs code and we can add the command for the new behavior here when the button is tapped.As usual the Command property is expecting an ICommand, add the following code to the MainViewModel and return a new instance of RelayCommand to execute whatever behavior you wish. In this example, I'm just doing a little popup to show whatever the user input into the myName TextBox.public ICommand AreYouSureCommand { get { return new RelayCommand((p) => { var msg = new MessageDialog(string.Format("Hi there {0}", p)); msg.ShowAsync(); }); } }See the result here:And that is EventToCommand for MVVMlight for Windows 8!There are many more behaviors in the WinRTBehaviors library that you should take advantage of, for me the most notable ones being FlipViewPanoramaBehavior and NavigationService being ported to Windows 8.