Our first task with the new view model system will be to connect the button clicks in the main menu with the display of the corresponding pages.

The quit button

To start with something simple, we’ll implement the quit button. (We’ll soon see that it’s not as simple as it seems…)

The communication between the view layer and the view model layer is established via bindings, events and commands. Bindings are (potentially) two-way connections, events are used to communicate something from view model to view, commands are used in the other direction. Commands are provided by the view models and bound to in the view. When for example a button is clicked and this button’s Command property is bound to a command in the view model, then this button “executes” the command and allows the view model to react on that command.

The view actually expects the command to be something that implements the ICommand Interface. WPF comes with a standard implementation for ICommand called RelayCommand.

RelayCommand

A command basically consists of two parts: A method that is called from the view to determine whether the command can be executed or not (CanExecute()), and another method to actually execute the command (Execute()). RelayCommand only consists of a constructor where both delegates are passed in. The class then automatically routes calls from the view to the corresponding delegate in the view model.

Note: if you for any reason don’t have access to the RelayCommand implementation in Microsoft.TeamFoundation.MVVM, here’s one you can use:

The Quit Command

Define a RelayCommand field named _quitCommand and encapsulate it with a property:

Define two methods ExecuteQuit() and QuitCanExecute() and create the command in the constructor:

For now we can simply call Application.Current.Shutdown() in ExecuteQuit() but we’ll be talking about this in a short while:

If we now bind the Command property of the quit button to this new command, then our application should be able to quit:

If we now extend our unit test to use the new command (or “click the quit button”)…:

…we’ll get an null reference exception at the line where Application.Current.Shutdown() is called. Application.Current is null and that is because WPF is not initialized in a unit test and therefore no Application object is available.
So you see, it’s not always a good idea to call WPF methods from view models…

Suggestion #5: Don’t call WPF System methods in view models.

In a real world project you will find a lot of situations where you shouldn’t be calling WPF methods from view models. Calling Application.Current.Shutdown() also chains your view models to be used with WPF – so you can’t use them in ASP.NET for example.

What we need now is a way to abstract the quitting of the application. Instead of calling Application.Current.Shutdown() directly, we need a method that can be called from the view models and that can be rerouted in unit tests.

The system connector

Create an interface named ISystemConnector. This will be the connection between the view models and the system and it provides the methods they need to call to do their job:

Since potentially every view model could need this interface, we will define it in ViewModelBase. Create a field, an encapsulating property and a constructor to initialize it:

We also have to adapt the constructor in PageVM:

And of course the constructor of MainMenuPageVM:

And since PageFrameVM also derives from ViewModelBase, it also requires a new constructor:

In SimpleMVVMApp we now need to add “something” that implements this interface:

Since this interface represents the “outer world”, we’ll pass in the implementation via the constructor and store it in a member variable:

Our MainWindow will be the implementation. So add the interface to the base list of the class MainWindow and implement the Quit() method. Finally add this to the constructor call of SimpleMVVMApp:

One last thing is missing. We have to fix our test. In our test the test class will be the implementation of the ISystemConnector interface. This allows us to verify whether methods in the interface are called correctly and mock the behaviour of the system where necessary. Add the ISystemConnector interface to the base list and implement the Quit() method; finally add this to the constructor call of SimpleMVVMApp:

We actually want to test whether the Quit() method has been called correctly; that means it should be called exactly once. Therefore we define a member variable in the class named _quitCallCounter and in the Quit() method we increment it; So we finally can test whether the Quit() method has been called correctly:

As you can see this approach is very flexible. You can use a WPF object as implementation of the interface, or you can use the test class. You could even use a completely different class to mock the behaviour of the UI.
The interface will grow over time but it is one interface that bundles all the requirements that the view models have, and therefore it is fairly easy to substitute it.