Click here to Skip to main content
Click here to Skip to main content

Model-View-ViewModel in WPF

, 21 Dec 2007
Rate this:
Please Sign up or sign in to vote.
An article on creating WPF applications, following the Model-View-ViewModel pattern.
Screenshot -

Introduction

The Model-View-ViewModel pattern, a variant of Model-View-Controller, provides a nice way to develop graphical applications that are testable. Several features in Windows Presentation Foundation, such as data binding and the command architecture, go along way towards making it possible to follow this pattern. Unfortunately, once you start to follow the pattern in a real application, you start to run into various things that make it very difficult to maintain the strict separation of Model, View and ViewModel. This article implements the basis of a full featured application, illustratring various techniques that may be used to maintain the strict separation of concerns demanded by the M-V-VM pattern.

Background

I tried to implement this application while following the Behavior Driven Development methodology. I've captured the attempt by including a complete version history, in the form of a Bazaar repository. Bazaar is a distributed version control system, and as such the entire repository was included in the downloadable source archive. You can see every step of development, including all of the various mistakes I made while coding.

Despite the attempt to follow BDD, don't expect production quality code here. First, I'm new to this methodology, and you can be certain I didn't follow it as well as one should. Second, though the project includes a fairly complete example application, it is only an example. I've focused on the necessary things to illustrate how to implement an application in WPF following M-V-VM, and not on what would be necessary to make a production worthy application. This is a starting place only.

Also, note that the unit testing code uses a lot of custom code. This was a large enough portion of the effort, that I split that out into a separate article: VisualStudio Unit Testing Extensions.

Using the Code

The "core" to a lot of the code in this project can be found in the ViewModel class. This class is both a MarkupExtension class, as well as a class providing a few attached properties. In order to associate your ViewModel with your View, you use the ViewModel class like this:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:c="clr-namespace:CodeProject.Windows.Markup;assembly=CodeProjectCore"
    xmlns:vm="clr-namespace:TaskList.ViewModel;assembly=TaskList.ViewModel"
    c:ViewModel.Instance="{c:ViewModel {x:Type vm:MainWindowViewModel}}">

Assigning the ViewModel.Instance attached property does several things:

  • Assigns the property to an instance of an object. Note that this property is inherited by children.
  • Assigns the DataContext property to the same instance.
  • Assigns the ViewModel.Commands property to the empty string.

That last bullet point is worth explaining further. The ViewModel.Commands attached property is used to create command bindings on the View for command handlers in the ViewModel. This is actually one of the trickier things to accomplish in a simple and "clean" manner. I've blogged about this on my blog (check out the archives for several posts on this topic), and others, such as Brownie, have as well.

When ViewModel.Commands is attached to an element, it searches the ViewModel.Instance for a property of type CommandBindingCollection with the CommandSinkAttribute with a matching KeyName. All CommandBinding instances in this collection are added to the element's Commands. This solution was inspired by the article Smart Routed Commands in WPF, though obviously the purpose and implementation is different here.

The ViewModel does not need to inherit from any base class, or implement any interfaces. The ViewModel markup extension will try to instantiate an instance of the ViewModel first by looking for a constructor that takes a single parameter compatible with the element. You should avoid creating a tight coupling to the View here, by using an interface that the element can implement. If the ViewModel doesn't have a constructor that fits the criteria here, it will instead be instantiated using the default contructor, if present. It's generally best to not create any coupling here at all, but there are some things you simply can't do in the ViewModel, such as navigate to another page, and a View specific interface allows you to put such code in the View while retaining as little coupling as possible.

A similar interface can be used for the Application. This allows the ViewModel access to application wide settings and functionality, while not being closely tied to the actual Application. The sample application demonstrates using both View interfaces as well as an application interface, including how to use Mock Objects that implement these interfaces to facilitate testing.

The goal with the ViewModel is to put as much UI state as possible into it. The View then binds this state to the necessary elements. The classic example here is the selection state for a collection that will be presented in the View. The problem is that some state in the View is given in read-only properties that can not be used in databinding. The SelectedItems property on several controls is an example of this. In order to maintain such state in the ViewModel a unique solution must be found to bind the state to the read-only properties on elements in the View. The Selection class provides an attached SelectedItems property to illustrate one way in which this can be accomplished. The attached property is responsible for watching state both on the element as well as in the ViewModel, and keeping the two in sync.

Bonus: DataErrorInfo

This class isn't really related to M-V-VM, the main forus of this article. So, consider it a bonus. This is the starting point for a validation framework based on IDataErrorInfo. It uses various ValidatorAttribute classes (only a StringLengthValidatorAttribute is included in the code, but it should be straight forward to create other validators) to specify how properties are supposed to be validated. The Task Model class illustrates the use, and the EditTaskPage shows how to do validation with it in WPF.

History

12/16/2007 - Initial article published.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

William E. Kempf
Web Developer
United States United States
Windows developer with 10+ years experience working in the banking industry.

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web04 | 2.8.140827.1 | Last Updated 21 Dec 2007
Article Copyright 2007 by William E. Kempf
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid