Getting started with Model-View-ViewModel (MVVM) pattern using Windows Presentation Framework (WPF)

,

The Windows Presentation Framework (WPF) is built to take full advantage of the Model-View-ViewModel (MVVM) pattern. Though it is possible to create WPF applications without using the MVVM pattern, a little investment in learning can make building WPF applications much simpler.
If you are just getting started with WPF I would suggest taking a look at this getting started guide.

 

Let’s look at the the three pieces of MVVM: Model, View, and View Model.

 

View: These are all of the UI elements, the pretty face of your application. For WPF, these are all of your XAML files. They may be Windows, User Controls, or Resource Dictionaries. Though it is certainly possible to construct the view entirely from code, the vast majority of the UI will (and should be) built with XAML. The view may be quite dynamic, and even handle some user interaction (see the Commands section below).

 

View Model: These are the objects that provides the data and functionality for each of your views. In general there is typically a one-to-one mapping between views and view model classes. The view model class, exposes the data to the view, and provides commands to handle user interaction. Unlike other design patterns, the view model should not know about its view. This separation of concerns, is one the key tenets of MVVM. The view model is the connection between the view and model.

 

Model: Broadly speaking the model provides access to the data and services that your application needs. Depending on your application, this is where the real work gets done. While the view model is concerned with pulling together the model’s data, the model classes perform the actual work of the application. If you are using dependency injection, the model classes will typically be passed as interface constructor parameters in your view model.

 

Since the interaction between the view model and the model will largely depend on your specific application, for the rest of this article we will focus just on the interaction between the view and the view model.

Bindings – Keeping it in context

The Binding engine is is what makes the MVVM pattern possible. Bindings are declared in the view, and link properties in the view back to properties in the view model.

 

The above code is the start of implementing the MVVM pattern. The Binding sets the value of the Text property to be the value in the FirstName property. If you were to run this code, the TextBlock’s Text would still be empty. This is because there is nothing linking the ViewModel class to the Window. In WPF this link comes from the DataContext property.

In the Window’s constructor we will set its DataContext. If no DataContext is specified on a UI element, it will inherit the DataContext of its parent. So setting the DataContext on the Window will effectively set it for every element within the Window.

 

Now, running the application, the TextBlock shows “Kevin”.

One of the best things about Bindings is they keep the UI in sync with the data in the view model. Let’s go and update the FirstName property.

If we run the application the TextBox will still show “Kevin”, not the updated value of “Mark”. Although the property’s value has been changed, there has been no notification to the Binding to update its value. We can fix this by implementing the INotifyPropertyChanged (INPC) interface. This interface has a single event that notifies the bindings that a particular property has changed and any bindings using it should re-evaluate their values.

We can implement it like this:

Now in the Window’s constructor we notify the view that the property has changed.

Now the binding properly updates to show “Mark”.

However, remembering to raise the event every time you change a property’s value can get very tedious. Because this pattern is so common, many MVVM frameworks provide a base class for your view model classes similar to the following:

 

This allows us to re-write our FirstName property like this:

The INPC event will be raised every time we change the FirstName property.

 

Related concepts for further reading

  • Complete WPF data binding documentation.
  • Specify the Binding’s source to use an object other than the DataContext for the binding. These are the Source, RelativeSource, and ElementName properties on the Binding.
  • Value Converters for transforming data in the view model’s properties to values that match the view.
  • String format on bindings for simple formatting of text data.
  • MultiBinding to bind multiple properties to a single element.
  • MVVMLight is a simple-to-use MVVM framework that comes with a ViewModelBase class similar to the example presented above.
  • CallerMemberNameAttribute allows the compiler to automatically inject the name of the calling member in the string parameter. This is used code above to allow the compiler to automatically supply the property name to the SetProperty method.

Commands

Bindings are a great way to move data from your view model into your view, but we also need to allow our view model to respond to user interaction. Most user controls that have a default user interaction, like a button click, are handled by commands. All user controls that implement the ICommandSource interface support a Command property that will be invoked when the control’s default action occurs. There are many controls that implement this interface such as Buttons, MenuItems, CheckBoxes, RadioButtons, Hyperlinks, etc.
Commands are simply objects that implement the ICommand interface. Or, put another way, Commands are messages from the View to your View Model. When the control’s default event occurs, such as button click, the Execute method on the command is invoked. Commands can also indicate when they are able to execute. This allows the control to enable or disable itself based on whether its command can be executed.

In our very simple example, we will change the value of the first name when a button is clicked.

First, we need to add a command property in our view model:

We will then add a button to the MainWindow and use a Binding to set its Command property to be the command in our view model.

 

Now we just need to assign a new command object to our ChangeNameCommand property in our view model. Unfortunately WPF does not come with a default ICommand implementation suitable for use in a view model, however the interface is simple enough to implement:

In this very simple implementation, an Action delegate is invoked when the command is executed. For now we will ignore the CanExecute parts of the interface and always allow the command to always be executed.

We can now finish the code in the view model.

 

If we run our simple application we can see that clicking the button does change the name.

Let’s go back and implement the CanExecute portions of the ICommand interface.

Just like the execute method, this command will also take in a CanExecute delegate. The CanExecuteChanged event is also exposed with a public method so we can raise it anytime the return value of CanExecute delegate has changed.

Back in our view model we will make the following additions.

CanChangeName will be invoked to determine if the command can be executed. In this case we will simply prevent the command from executing once the name has changed to “Walter”. Finally after changing the name in the OnChangeName method, the command notifies the button that its CanExecute state has changed by raising its event.

Running the application we can see that the button properly disables after the name is changed.

Related concept for further reading

  • Command parameters for passing in an argument to the command. This is the object that will get passed the Execute and CanExecute methods in the DelegateCommand shown above.
  • MVVMLight is a simple to use MVVM framework that comes with a couple RelayCommand objects that can replace the DelegateCommand object shown above.
  • Routed commands for handling UI interaction from controls.

 

 

WPF is designed with the MVVM pattern in mind. Though it does require a bit more learning to understand it, once you have mastered the basic concepts, it can actually make building a WPF application much simpler. By intentionally separating the concerns of each area of the application, you will end up with a more maintainable application that is easier to unit test.

You can see the complete solution here.

Leave a Reply

Your email address will not be published. Required fields are marked *