Motivation
We have became accustomed to using design patterns to solve common and complex problems that recur often in software engineering and also in our lives. A common pattern that applies to presentation XAML based solutions is the Model-View-ViewModel pattern or MVVM. This pattern applies when creating solutions targeting Windows Store Applications (Win RT), Windows Phone, WPF systems and Silverlight applications and it is consider best practice for these kinds of solutions.
There is nothing wrong in implementing the MVVM pattern from the ground up however delegating on a mature framework such as MVVM Light or Microsoft PRISM always produce benefits including reducing implementation time and also the number of defects introduced "while re-inventing the wheel". These frameworks also resolve complex issues in an elegant and simple way allowing us to focus on our business case instead of dedicating resources to duplicate what other teams have already accomplished.
This note starts me on a journey to rediscover the MVVM design pattern under the umbrella of PRISM in preparation for a 10 minutes presentation that I am planning to deliver at the
BC .Net User group for the month of December of 2014 and because I had the opportunity to create a small WPF solution, I decided to implement the PRISM pattern and then move the learned concepts into the creation of a small Windows Store Application, possibly creating a Universal App.
So, here we go!
MVVM
This study does not dive into MVVM, nor it demonstrates its awesomeness; it just uses it. The first time I heard about this pattern was in 2011 when I was taking a Silverlight course from Medhat Elmasry at
BCIT. However, it is worth mentioning that MVVM (
Model-View-ViewModel) is an architectural pattern used widely in software engineering which originated from Microsoft. This pattern is largely based on the
Model-View-Controller (MVC) pattern (saying this has caused me grief in the past with some folks).
MVVM helps separate the business and presentation logic of an application from its user interface (UI). It supports event driven programming, and it is the recommended pattern when creating solutions using .NET platforms and XAML.
Installing Prism MVVM for WPF
Why use Prism in the first place?
The framework encourages good practices, modularity, view discovery using an Experience mechanism which associates a ViewModel with its View. This helps add semantics and conventions to our solution. By the same token, one of the great benefits of MVVM is that solutions can be designed with testability in mind.
Although not explored in this note, PRISM MVVM works very well with other frameworks such as Unity for dependency injection. The Unity framework was also created by the Microsoft Practice and Pattern team: these folks are smoking!
Adding PRISM to a solution is very simple and it can be downloaded from CodePlex or installed via NuGet. I like easy, so I went NuGet for this note.
Once the framework has been installed expand the reference node in solution explorer and you will notice 7 new references including Prism.Mvvm, which provides the MVVM framework subject of this note.
It is also worth mentioning Prism.PubSubEvents which is used as event aggregator to address tightly coupled .Net events. Event aggregators are also used within the PRISM framwork to send messages between modules and between different objects. Another interesting library that has been added to the project is the Prism.ServiceLocation which offers a navigation service within the Prism framework. These are important features of the Prism framework which I will soon return to.
Using Prism MVVM for WPF
The application used to apply this pattern as a proof of concept,a learning tool, is very simple and what it does is load a collection of players, from different teams with their high score and the number of stars that they have collected. Assume that your business analyst have provided you with this screenshot:
From the "design" document two views are identified; a MainWindowView and a PlayerItemView. From these views, properties of the ViewModels that support these views are identified.
 |
| Note that this View uses an ItemsControl which could be used in PRISM as a Region where other views can be placed. Regions are not discussed in this note. |
So, what does a model able to support MainWindowView needs?
- ICommand property to Fetch data.
- ICommand property to Clear data.
- Observable Collection of Player Item View Models
What does a model able to support PlayerItemView needs?
- Player Name.
- Team Name.
- Team Color.
- High Score.
- Total Stars available.
- Total Stars obtained.
You can take a look at the implementation of these View Models by downloading the sample code. It is very simple. Note that although it is not required by PRISM, the ViewModels were defined in their respective interfaces.
Views, PRISM IView and View - ViewModel Discovery
In a basic implementation of PRISM, and this note is just that, each view which is associated to a ViewModel needs to implement Microsoft.Practices.Prism.IView. This is required by the PRISM discovery mechanism.
The way the View and ViewModel are associated is by Experience. Experience is a string which forms part of the name of the View and ViewModel and it is shared by both objects. For example; experience string Main:
Experience: Main > View: MainWindow > ViewModel: MainWindowViewModel
Note that this is just a convention and it can be changed. However, this mechanism only works when the property AutoWireViewModel is set to true in the prism ViewModelLocator object.
From MSDN:
Prism’s ViewModelLocator class has an attached property, AutoWireViewModel that when set to true will try to locate the view model of the view, and then set the view’s data context to an instance of the view model. To locate the corresponding view model, the ViewModelLocationProvider first attempts to resolve the view model from any mappings that may have been registered by the Register method of theViewModelLocationProvider class. If the view model cannot be resolved using this approach, for instance if the mapping wasn't created, the ViewModelLocationProvider falls back to a convention-based approach to resolve the correct view model type. This convention assumes that view models are in the same assembly as the view types, that view models are in a .ViewModels child namespace, that views are in a .Views child namespace, and that view model names correspond with view names and end with "ViewModel."
In this basic implementation I used the convention approach,
the experience string, and placed Views in the Views namespace and ViewModels under the ViewModels name space and named the objects as per the convention requirement
The in the XAML of the view a reference to PRISM is includes and the AutoWireViewModel is set.
 |
| Note that you need to include xmlns:prism="clr-namespace:Microsoft.Practices.Prism.Mvvm;assembly=Microsoft.Practices.Prism.Mvvm.Desktop" |
In the above example you can see that nor the XAML or the code behind of MainWindow contain a reference to the ViewModel. The framework is associating these two together through the ViewModelLocator. The ViewModelLocator is a new feature for PRISM WPF which is also included in PRISM for Windows RT.
PRISM also offers other mechanisms for this association by registering a view type against a region name. This discovery approach uses RegionManager and it is not discussed here.
Design Time
Although not required by PRISM WPF, the development experience can be enhanced by using design time ViewModels. For this reason, it is recommended to define ViewModels with an interface which is implemented by a runtime and a design time view model respectively. There is some duplication in doing this, however, a clear advantage can be seen in the next image.
 |
| Using a Design time ViewModel provides advantages while working with the designer or Blend. |
In the above example interface IPlayerItemViewModel defines the view model which is implemented by a view model object which will be used at run time and a design time view model used only at design time and not used at run time.
Note that in the designer view the value converters code work and convert the enum Team TeamColor into the name and the Brush to color the background of the layout container. The design time values set in the constructor of the design time view model are displayed in the designer. This is great because it is providing us with a real look and feel of the view while we are designing it without the need to run the project to see what it would look like.
Time to Reflect: When Using MVVM, does this mean no code behind?
This could be up for debate and we have a "binary" number of schools out there: "No-Code-Behind" versus "Yes-Code-Behind"... there is no in between because even if you place "just a little bit" of code behind, well, that is "Yes-Code-Behind", right?
I belong to the "It-Depends-What-It-does-Yes-Code-Behind" school, which is pretty much in the basement of the "Yes-Code-Behind" school. I feel that if the code behind does work which concerns to the UI logic then it would be "OK" to place it in the code behind and this does not break the MVVM pattern.
I would be breaking the pattern in the case that the code behind was executing code which concerns to the business or application logic; like for instance talking to a service or repository to get or update data which is really the responsibility of the ViewModel.
Which one is your school?
Conclusion - A Basic PRISM Implementation
- Add the framework through NuGet to your solution.
- Every view which has a ViewModel must implement IView.
- Views use ViewModelLocator.AutoWireViewModel set to true.
- Take into account an Experience string when naming a view and its view model.
- Optional: Use a design time ViewModel which facilitates your work in the design and using Blend because you see in the designer the view at design time.
Download the Sample Code
The sample project was created using Visual Studio 2013 Ultimate and you can download it from the following location:
DOWNLOAD.
References: