Understanding the MVVM Light application sample
When you create a new MVVM Light project, the created application can be run, and shows a sample of functionalities available in the toolkit. This page explains the functionality available in the MVVM Light sample application. Later, in-depth posts will be published explaining some of these classes and components more in detail. But for now, let’s concentrate on the simple example:
File structure
The solution is structured as follows:
Solution and files for WPF
Solution and files for Silverlight
- Top level: View elements. Some developers like to place the View elements (Windows, UserControls, etc…) in a subfolder named View. I prefer to have them at the top level, it makes it easier to find them and edit them (especially in Expression Blend). If the projects gets very complex, you can even create a whole new project for the View.
The WPF sample application has only one Window: MainWindow.xaml
The Silverlight sample application has only one Page: Page.xaml - Folder “Model”: This is the application’s data/service layer, pulling data come from a database, Internet, services, etc…. In this sample application, the Model folder contains only an Item class which is passive. In a more complex "real life" application, this would host a service retrieving and updating data.
- Folder "Skins": The file MainSkin.xaml is a resource dictionary which is merged into the main application’s global resources (App.xaml). It contains all the "skinnable" features that define the look&feel of the application.
- Folder “ViewModel”: The ViewModel is a layer which is placed between the Model (data) and the View (UI). It serves as a separation layer, prepares the data for data binding, converts certain types in other types, executes commands, etc. It is a central component of modern WPF and Silverlight applications. To know more about View Models and the MVVM pattern, check the
Get Started page. The ViewModel folder contains the following classes:
- ViewModelLocator: This class acts as a service and manages the life time of the UI View Models (such as MainViewModel). It exposes methods and properties allowing to easily control the creation and deletion of such ViewModels.
The ViewModelLocator is a central component of the pattern as it is implemented in the MVVM Light Toolkit. It is added to the View in the file App.xaml with the following code:
- ViewModelLocator: This class acts as a service and manages the life time of the UI View Models (such as MainViewModel). It exposes methods and properties allowing to easily control the creation and deletion of such ViewModels.
<!--Global View Model Locator-->
<vm:ViewModelLocator x:Key="Locator"
d:IsDataSource="True" />
with
xmlns:vm="clr-namespace:MyMvvmProject.ViewModel"
- MainViewModel: This is the ViewModel for the UI (MainWindow.xaml or Page.xaml).
It exposes properties that are used to enhance the user experience.
This class inherits GalaSoft.MvvmLight.ViewModelBase, one of the classes contained in the assembly GalaSoft.MvvmLight.dll (referenced by the application).
In this sample, the ViewModel detects if the code is executed into Expression Blend (design mode) or in runtime. If it is executed in Blend, mock data is created to help the designer’s work.
The MainViewModel is linked to the main window (or page) in the application. The window (or page)’s DataContext is set to the instance of the MainViewModel, through the ViewModelLocator’s services:
<Window x:Class="MyMvvmProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding Main, Source={StaticResource Locator}}">
- ItemViewModel: This is a wrapper around the Item class from the Model layer. It is used to prepare data for data binding.
This class inherits GalaSoft.MvvmLight.ViewModelBase, one of the classes contained in the assembly GalaSoft.MvvmLight.dll (referenced by the application).
Design time experience (Blendability)
The ViewModels are design-time enabled. You can open the SLN file in Expression Blend and notice how the items used are now design time items. This enables the designer using Blend to create styles, templates and to work on the application’s look&feel without obstacles.
In the picture below, notice how the ListBox displays different texts in Blend than in runtime. Being able to open a UI in Expression Blend, and being able to easily modify the behavior of the code to make it “Blend-safe” is known as Blendability. For example, attempting to connect to a Database, or to the Internet might cause Blend to fail to render the UI. Using the ViewModel approach of the MVVM Light Toolkit, you can easily render your UI into Expression Blend anyway.
Commanding in WPF (RelayCommand)
WPF proposes a way to decouple the UI (the View) from the code (the ViewModel) and to avoid using events. Without going too much in the details, handling events (for example Button.Click) forces a tight coupling between these two layers, and complicates the work of the designers, hinders the testability and the maintainability of the code.
To avoid this, some WPF controls expose a Command property, which can be data bound to a property in the ViewModel of type ICommand. To make this easier, the Toolkit exposes two classes: RelayCommand and RelayCommand<T>. These two classes are explained with many details in a separate blog post.
To use a RelayCommand in WPF, declare the command in the ViewModel:
/// <summary>
/// Gets the command executed when the main button gets clicked.
/// </summary>
public RelayCommand ButtonCommand
{
get;
private set;
}
and instantiate it in the constructor:
this.ButtonCommand = new RelayCommand(() =>
{
// Do something here.
});
Note: This uses the syntax called “lambda expression”. If you prefer, you can also use a reference to a method or a delegate.
In XAML, use the command with:
<Button Content="{Binding ButtonContent}"
Command="{Binding ButtonCommand}" />
If you wish to pass a parameter to the command, use RelayCommand<T> where T is the parameter’s type. For example:
/// <summary>
/// Gets the command executed when the main button gets clicked.
/// </summary>
public RelayCommand<string> ButtonCommand
{
get;
private set;
}
and instantiate it in the constructor:
this.ButtonCommand = new RelayCommand<string>(s =>
{
// Do something here.
// s is the string parameter.
});
Usage in XAML:
<Button Content="{Binding ButtonContent}"
Command="{Binding ButtonCommand}"
CommandParameter="{Binding ElementName=MyTextBox, Path=Text}" />
Commanding in Silverlight (RelayCommand and ButtonBaseExtensions)
Silverlight, even though it exposes the ICommand interface, doesn’t offer a good support for commands in general. To mitigate this, the Toolkit offers the RelayCommand, RelayCommand<T> and a Silverlight-only class named ButtonBaseExtensions. This is all explained with many details in a separate blog post.
To support commands in Silverlight, the syntax is slightly different than in WPF:
<Button Content="{Binding ButtonContent}"
cmd:ButtonBaseExtensions.Command="{Binding ButtonCommand}"
Grid.Row="2"
Margin="10" />
with
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight"
With parameter:
<Button Content="{Binding ButtonContent}"
cmd:ButtonBaseExtensions.Command="{Binding ButtonCommand}"
cmd:ButtonBaseExtensions.CommandParameter="{Binding ElementName=MyTextBox, Path=Text}" />
Note: Even though the solution we propose here allows using Commands in Silverlight, there is no CommandManager in this platform, hence the controls will not automatically be disabled/enabled. If you need to disable/enable a control using a RelayCommand in Silverlight, use the method RelayCommand.RaiseCanExecuteChanged as explained here.
Messaging
Often, a ViewModel needs to communicate with other ViewModels in the application. Or maybe it needs to send a message to its View. Or maybe a View wants to communicate with other Views, or with the Application object. There are multiple scenarios where a loosely coupled messenging system makes sense.
The Toolkit exposes a set of classes to make this easier, in the assembly GalaSoft.MvvmLight.dll. More information about the Messenger will follow, but there is already one place in the sample application where we can see the Messenger at work. Open the file MainViewModel.cs and observe what the ButtonCommand code executes (this code is placed into a lambda expression, but it could be placed inside a method, etc…):
var dialogMessage = new DialogMessage(
this,
typeof(MainWindow),
Resources.MessageBoxText,
r => DialogResult = r)
{
Button = MessageBoxButton.YesNo,
Caption = Resources.MessageBoxCaption,
DefaultResult = MessageBoxResult.No,
Icon = MessageBoxImage.Question
};
Messenger.Default.Send(dialogMessage);
This code creates a DialogMessage (also a class exposed by the Toolkit). There are multiple types of messages available in the namespace GalaSoft.MvvmLight.Messenging. The last parameter of the DialogMessage constructor is a callback (implemented here as a lambda). This snippet of code will be called by the message recipient, in this case when the dialog box is closed by the user. This way, the ViewModel is notified that an action occured at his request.
Note that in the Messenger from V2, you can send any object or simple value that you want through the Messenger.Send method. Specialized message classes are convenient, but not absolutely needed for communication.
In the sample, the default instance of the Messenger class is used to send the message. You can create other Messenger instances if you wish, to create specialized communicaiton channels.
The MainViewModel (sender) does not know if there is a recipient for this message. In the sample, the recipient (MainWindow for WPF, Page for Silverlight) registers with the Messenger’s default instance in its constructor. Note that a recipient only receives message types that it registered for, but of course a recipient can register for multiple message types, or multiple actions for one given message type. And of course, there can be multiple recipients for one message type too.
Messenger.Default.Register<DialogMessage>(
this,
HandleDialogMessage);
The method HandleDialogMessage is in charge of receiving and acting on this specific type of messages. In the sample, it displays a message box based on the information contained in the message. If the sender (the ViewModel) provided a callback method (which, in our sample, it did), then the callback method is called so that the sender receives the result that the user clicked.
private void HandleDialogMessage(DialogMessage message))
{
if (message == null)
{
return;
}
if (message.Sender.GetType() == typeof(MainViewModel)
&& message.Target == typeof(MainWindow))
{
var result = MessageBox.Show(
this,
message.Content,
message.Caption,
message.Button,
message.Icon,
message.DefaultResult,
message.Options);
if (message.Callback != null)
{
message.Callback(result);
}
}
}
Note that messages can carry all kind of information. The DialogMessage shown here specifies information about the message to display, but the View is responsible for displaying the message box. I later the designer decides to replace a message box with a modal window or any other kind of dialog, the ViewModel doesn’t need to be modified.
This small sample is not making justice to the Messenger class which is a very powerful and versatile component. Stay tuned for more documentation coming up.
Localization
In the sample, the title of the window and the strings are localizable. Localizable strings are stored in the folder Properties / Resources.resx
Note: This simple approach to localization is only viable for small projects. For a more elaborate and powerful approach to localization using RESX files, please refer to Tim Heuer’s blog. Also worth checking, WPF localization guidance on Codeplex.




