Sunday, February 27, 2011

MVVM Light for Silverlight Part 2: The Glue


Tools: VS2010 | C# | Silverlight 4 | MVVM Light Toolkit V3 SP1

The Glue

It's what holds an MVVM application together, the ViewModel. While part 2 is about more than just the ViewModel, its important to know that the ViewModel is the class responsible for getting data and making it available. This is the second post in the MVVM Light for Silverlight series. You can view the first post here: MVVM Light for Silverlight Part 1: Introduction. This time around we'll create an MVVM Light project and walk through some of the basics. We will be using VS2010, Silverlight 4, MVVM Light Toolkit, and C#.

Agenda

Install: MVVM Light Toolkit and template
Create: MVVM Light project
Overview: MVVM Light Project Template
How it works: MVVM Light

Installation

We are going to create an MVVM Light SL project by way of template. You can download the toolkit here, and the template here. Need help with installation? Go here.

Creating the Project

Fire up Visual Studio 2010 and click File->New->Project (Ctrl+Shift+N) to create a new project. In the left most pane (your template tree), make sure 'Installed Templates' is selected, and expand the Visual C# tree node and select Silverlight. From the available templates select MvvmLight(SL) and click OK.



MVVM Light Project Template Overview

Expand the references node in solution explorer and straight away you should notice that there are a few new DLLs that should be referenced in addition to the standard silverlight application dlls.




MVVM Light Components:

For detailed information on the components use this reference.

Component Overview
  • GalaSoft.MVVMLight - This dll contains the core classes that make up MVVM Light
    • ViewModelBase class - used as the base class for your view models
    • Messenger classes - used to communicate within the application
    • Command classes - Simplifies commanding in application
  • GalaSoft.MVVMLight.Extras
    • EventToCommand class - allows you to bind an event of a ui element to icommand
    • Helper class - aids in creation of multithreaded applications
  • System.Windows.Interactivity- Windows DLL, referenced for behaviors
If you are missing any of the DLLs you can get them here.

Compile and make sure everything is working out of the box. Run the application to verify everything is in working order. You should see the following: Welcome to MVVM Light. Thanks Laurent, that was easy.
If you want you can modify and resave your template and create a folder in the root of the project named Views. This helps me to more easily distinguish my views from any other files. Just add the folder, and click File->ExportTemplate.

Files and Folders

MainPage.xaml -The default View.
ViewModel [Folder] - Default location to store your ViewModels.
MainViewModel.cs - Default ViewModel
ViewModelLocator.cs -Class intended to locate the ViewModel we intend to use
Model [Folder] - Default location to store your Models
Skins[Folder] - Default location to store your skins/themes
MainSkin.xaml - Default skin/theme (empty by default)

How it works

The View

Used to display the UI. Open the default view, MainPage.xaml. The goal of this Main View is to bind to the MainViewModel (MainViewModel.cs) and present a View to the user. This is accomplished in the definition of the MainPage user control by setting the DataContext and using the ViewModelLocator (ViewModelLocator.cs) as follows:

DataContext="{Binding Main, Source={StaticResource Locator}}">

The above code snippet binds 'Main', which is our instance of the MainViewModel (defined in ViewModelLocator.cs), to the DataContext of our Main View (MainPage.xaml). 'Locator' is defined in the App.xaml under the application resources. We define a ViewModelLocator instance and set the key to Locator as follows:

<Application.Resources>        
        <vm:ViewModelLocator d:IsDataSource="True" x:key="Locator">
    </vm:ViewModelLocator>
</Application.Resources>

This is how we set up an instance of our ViewModelLocator class as a resource. The isDataSource property indicates that this property is a data source and can be attached to a data control.

ViewModelLocator

Used to locate an instance of your ViewModel. If you open up the ViewModelLocator.cs, you will see that inside the ViewModelLocator constructor we initialize an instance of the MainViewModel. The MainViewModel is defined inside the ViewModelLocator class as a private static member(_main). A static property is defined (MainStatic) to access the instance of our ViewModel (_main), which is done through accessing the non-static property Main.

private static MainViewModel _main;

public static MainViewModel MainStatic

public MainViewModel Main

Inside our MainStatic property we initialize our MainViewModel instance using CreateMain(), if one doesn't already exist, and then return this instance inside the get accessor. Reference the code below:

/// 
/// Gets the Main property.
/// 
public static MainViewModel MainStatic
{
    get
    {
        if (_main == null)
        {
            CreateMain();
        }

        return _main;
    }
}

Inside the ViewModelLocator class we have a public static Cleanup method which simply calls ClearMain(), which in turn calls our ViewModel's cleanup method which cleans up the ViewModel. The cleanup method being called by _main.Cleanup() is a method of the ViewModelBase class and unregisters the instance and provides basic cleanup for your ViewModels. It can also be overridden to cleanup additional resources.

ViewModel

The ViewModel is responsible for the bulk of the logic for our view. We might be accessing a data model, calling services, performing various calculations, etc. Open up MainViewModel.cs to quickly analyze the default ViewModel. Yep, thats it. There isn't much needed for a default view model. A property and a constructor. Notice the MainViewModel derives from ViewModelBase, the base class for ViewModels in MVVM Light.

public class MainViewModel : ViewModelBase

Inside the ViewModel constructor you can hookup Models, provide logic, run additional initialization, etc. You can also specify what happens to design time data when a design tool like Blend is being used and in design mode. The IsInDesignMode flag is a property of the ViewModelBase class, and allows you to determine if design mode is active. This helps allow for the Blendability of the application. You can specify sample data or other data that is immediately accessible in design mode for a friendlier designer experience, as opposed to waiting for some binding or other run-time method that you use to hookup your data to a control.

/// 
/// Initializes a new instance of the MainViewModel class.
/// 
public MainViewModel()
{
    if (IsInDesignMode)
    {
        // Code runs in Blend --> create design time data.
    }
    else
    {
        // Code runs "for real"
    }
}

There is a default public property named Welcome that simply returns the string 'Welcome to MVVM Light'. This is the message that is displayed when you run the application.

public string Welcome
{
    get
    {
        return "Welcome to MVVM Light";
    }
}

So how does the Welcome message show up on our view (MainPage.xaml) when it exists here in our ViewModel?

Remember in our View we bound the datacontext of the View to our ViewModel (MainViewModel)using the ViewModelLocator, and referenced it using 'Main'. Now that we have the ViewModel bound to our View's DataContext, we have access to the properties in the ViewModel. Inside the LayoutRoot in our view we bind the Text property of the TextBlock to the Welcome Property in our ViewModel.

<TextBlock Text="{Binding Welcome}">
</TextBlock>

We have now shown how you can have a View that is displaying information from an independent ViewModel. This illustrates the idea behind MVVM and shows us why MVVM Light is a useful tool for producing an MVVM Application. We have separated our code into manageable pieces, and produced a view with no code behind that binds to a ViewModel that services the View. We can now change the View or the ViewModel without affecting the other, if we choose. We can re-use the logic in the ViewModel for other Views or create new Views to represent our data in a different way.

ViewModel

The same concept is used for a Model. If we had a data model here we could create an instance or access it using the ViewModel. You may have validations or simple logic to deal with the data inside the Model, but the general purpose of the Model is to house the data. You can use ViewModels to perform various tasks and services to get data from a Model. After the ViewModel has the data you can then make the data available to the View.



Closing

MVVM Light is a quick way to setup an environment for developing an MVVM Application. There is a handful of light weight but powerful components that makeup the MVVM Framework. We discussed the basics of the MVVM Light. You should now be familiar with MVVM Light Installation, how to create a project, understand the components that make up MVVM Light, and how to get started with an MVVM Light project template. You should now have a clearer understanding of how MVVM Light works and how MVVM Light takes advantage of MVVM.

Next in the series: MVVM Light for Silverlight Part 3: Commands

No comments:

Post a Comment