In this post I’ll create the simplest application that covers the basics of MVVM in the context of unit testing. The application does just click counting - it’s the simplest app that I could think of that can be used to demonstrate view models,
INotifyPropertyChanged, data binding, commands and unit testing. We will NOT be using any MVVM frameworks.
The destination: Click Counting App
This is what we aim for:
This application is so barebones that the model if we choose to implement it would have just one property:
ClickCount and no logic inside it. This property is better suited for the view model - even the
click keyword suggests that.
The View Model
In order to support data binding between the view and the view model we’re going to implement the
But first: what the heck is data binding and why do we need it? Data binding is simply a way to automatically synchronize the changes between the view and the view model. So, if one changes, then the other will change as well.
This “automatic” behaviour is done using events (which are in turn an implementation of the Observer design pattern). That event is called
PropertyChanged and it is used by the view to subscribe to changes in the view model when the
DataContext property is set on the view (in our case
In order for the view to know that you have the
PropertyChanged event so it can subscribe to it you have to implement the
INotifyPropertyChanged interface. Here’s how to do it:
Here’s what Microsoft has to say regarding the naming conventions:
Typically, to raise an event, you add a method that is marked as protected and virtual. Name this method
OnEventName; for example,
OnDataReceived. The method should take one parameter that specifies an event data object. You provide this method to enable derived classes to override the logic for raising the event. A derived class should always call the
OnEventNamemethod of the base class to ensure that registered delegates receive the event.
In our case, we didn’t respect the convention fully: we needed to also provide the sender and the event argument instead of the changed property name. We did it like this because this is the most common/simplest approach in this case. This is the only place (that I know of) where the convention is not respected.
Well, now we have the event in place, but we also need the property that will use it. We just need to declare the property and be careful to call
OnPropertyChanged in the
Normally, we would have to specify the name of the changed property (like this:
OnPropertyChanged("ClickCount")), but since we’re using the
CallerMemberName, this will be automatically filled in based on the member that calls the method (in our case the
The next step is to implement the actual click counting behavior. For this, we’re going to use commands. In WPF, commands have to implement the
ICommand interface, so let’s do this:
In this post, to keep things simple, we’re going to ignore the
CanExecuteChanged event and the
CanExecute method will just return
true - we will always allow the execution of the command.
IncreaseCountCommand has to know about the view model in order to increase the
ClickCount so we’re going to provide it as a constructor argument.
The final step is to implement the
Execute method which in our case will just increase the
ClickCount from the view model.
Besides defining the command, we also need to add a property in the view model and initialize it in the constructor:
The view model tests
We’re going to use the default unit testing framework available. Normally I’d use NUnit, but to keep the example as simple as possible I’ll just use the default since it’s good enough. Here are the tests:
You should pay attention especially to the second test since it shows how to test the command. In this case we don’t have any parameter for the command, but I chose to use the
"ignored" string instead of
null to make it very clear that it’s not used. The test is following the Arrange, Act, Assert pattern which allows clear separation between the steps.
This can be created directly using the visual designer by creating 2 rows in the default Grid and drag and dropping a
TextBlock and a
Button on each row. Here’s the full
You should pay attention how the view model is associated with the view by using the
DataContext property of the
You should also pay attention how we access the view model properties from the view using data binding:
The full source code is available on GitHub. You can clone the repo and try it locally.