Better User and Developer Experiences – From Windows Forms to WPF with MVVM: Part 7, MVVM

I mentioned in the introduction that a new architectural pattern has emerged for Windows Presentation Foundation: Model-View-ViewModel.  As I mentioned, MVVM can make developing applications in WPF efficient, quick, and highly maintainable.  Now that I’ve covered some of the basic technological advances in WPF, mainly Data Binding, Commands, and Templating, it’s time to bring everything together, and demonstrate how this improves our jobs as developers.

As I mentioned in the section on templating, WPF’s design strives to maintain a clear separation between presentation and logic.  We’ve seen some of the advantages in terms of control creation – unlike Windows Forms, we can completely change the way a control looks merely by creating a new template, using XAML in a completely declarative form.  No code is required.  We get more flexibility with less work.  By separating presentation and logic, WPF creates opportunities for much greater degrees of flexibility in our applications.

As a developer, I see this as a very “good thing”.  The Model-View-ViewModel pattern has one goal – to extend this same flexibility into our applications by creating and maintaining a clean separation of concerns through our entire application.

In order to understand MVVM, I will start off by defining our distinct concerns, the individual “parts” of our application. 

I already defined our arguably most important concern: the Model.  Again, the Model is the domain-specific data and logic used within your application.  It’s the goal – the “data” you’re working to expose to your users.  This may be customer records in a database, or product information on a website, or anything else.  In our case, it’s two classes, the Feed and the FeedItem class.  In Model-View-ViewModel, our goal is to keep the model unaware of the specific application or technology that’s using it.  The Model knows about itself, and nothing else.

The second concern I’ll discuss is the View.  The View is the entire user interface of your application – it’s everything the user’s interact with directly: every control, every button, every check box, every window.  As I mentioned in part 3, WPF changes how the View is normally defined.  Instead of developing the user interface via code, we use XAML to create an XML-based, declarative description of the interface.

Let’s review our goal of maintaining a full separation of presentation and logic, this time just in terms of the View.  When we create our user interface, we want to define what the user will see (presentation) without worrying about how the program works (logic).  XAML is perfect for this, as it lets us design the user interface with zero code involved.  This gives us an easy way to think about our View in terms of our goal: The user interface should be declared entirely in XAML, with zero code behind.

Succeeding in this goal has many advantages.  It makes the View very flexible – a designer can take our View and stylize it or change it in any way desired, without changing or effecting a single line of code.  Also, if there is no logic in the View itself, it eliminates the risk of “stale” or unused code creeping into the View, which often happens in Windows Forms.

Now that we have the View and the Model defined, we need a way to hook the two things together.  Something has to coordinate our actions between the Model and the View, so that the user’s interaction has an effect on the Model.  This is handled by our third concern: the ViewModel.

The ViewModel serves the purpose of adapting the Model to be directly usable by the View.  In order to do this, we take advantage of WPF’s incredible Data Binding support.  In MVVM, the ViewModel sits between the View and the Model, and basically acts similar to an Adapter – it translates the properties and methods of the Model to a form that can be directly used via Data Binding.

The ViewModel also provides us a place to manage application state and logic.  By taking advantage of WPF’s Commanding Infrastructure, we can define ICommand instances in the ViewModel that the View can directly access via Data Binding.  This provides us a clean way to keep the logic out of the View – again, the View works completely via Data Binding to the ViewModel.  This provides a means by which we can hook into logic from the View without having the logic be tied to the specific view that is using it.

Here is a diagram illustrating our three areas of concern:

MVVMThere are some important aspects of this diagram I will discuss, for each of our Concerns, some critical points

  • The Model
    • The Model is unaware of anything except itself
    • The Model could be used by any form of program, and is not tied to a specific framework or technology
  • The View
    • The View is defined entirely in XAML
    • The View only needs to know what to bind to, by name.  It does not need to know anything about what will happen when properties change or commands are executed.
    • The View’s state is completely based upon data binding
  • The ViewModel
    • The ViewModel knows nothing about the View
    • The ViewModel directly interacts with the Model, in order to expose it for data binding
    • The ViewModel manages the Application-specific information

The advantages here are profound:

Our Model, since it is self contained, can be used in any way we wish.  If, later, we decided we needed a web-based API to the same model, we could use the Model unchanged.  If the successor to WPF comes along, and we need to update our application to use it, the Model remains unchanged.

Our View, since it has no logic, is completely designable.  The View can be modified by a designer with little or no programming experience, with no fear of breaking the logic.  The only knowledge that the designer needs to know is what properties and commands are available, and their names – everything else is handled directly by the framework to make it work.  This leads to a tremendous amount of flexibility in the View – the entire look and feel of an application can be changed at any time.

Our ViewModel gets a nice advantage from this architecture, as well.  Since it is not tied to a specific View, it is very easily testable.  The logic of our application is all exposed through self-contained ICommand implementations, which are easy to test.  The data is exposed via properties; again, easy to test.

There is still one issue left to resolve, though.  At this point, we know how to architect a single window or form correctly – the Model is used by the ViewModel, and the View “hooks” into the ViewModel with data binding.  This works great for a single user control – but we still need to create and wire up the controls in the first place.

At first glance, it seems like we’d need to know about the View and the ViewModel in order to do this.  For the ViewModel to be used as a binding source, it needs to be set as the DataContext of the correct View.  We need a way, given a ViewModel, to construct a View and set its DataContext.  In order to do this, we break one of our rules – the ViewModel, in order to construct the View, needs to know about the Views.

WPF, again, provides us with the final tool required for MVVM: Templating.  The same mechanism that our ListBox used when we discussed templating can be used for our ViewModel.  Instead of trying to construct our View, we can setup a simple DataTemplate that specifies that our View is used to render our ViewModel.  This will look similar to:

<DataTemplate DataType="{x:Type local:OurViewModel}">
    <local:OurView />
</DataTemplate>

This DataTemplate tells WPF that, any time we say to directly render an instance of OurViewModel, it should construct an instance of OurView, place it at that location, and set the DataContext of the OurView instance to the instance of OurViewModel.  Basically, WPF will do all of the work for us, just be specifying a DataTemplate.

Since DataTemplates are definable in XAML, and will propagate downwards through the Visual Tree in WPF, this lets our View automatically set itself up.  All that needs to happen is to provide a ContentPresenter in our View which binds, using standard DataBinding, to a ViewModel, and WPF will do all of the plumbing for us!

WPF adds three profound features: Data Binding, Commands, and Templates.  By using these three feature sets appropriately, we can redesign the architecture of our applications by using the Model-View-ViewModel pattern. This maintains a clear separation of concerns, allows for easy changes and redesign of the View, provides good testability, and keeps our domain specific classes completely isolated.

… Continued in the Conclusion …

About Reed
Reed Copsey, Jr. - http://www.reedcopsey.com - http://twitter.com/ReedCopsey

Comments

10 Responses to “Better User and Developer Experiences – From Windows Forms to WPF with MVVM: Part 7, MVVM”
  1. Pete says:

    When I first scanned this,what stood out to me was this bold quote:

    “The user interface should be declared entirely in XAML, with zero code behind.”

    While I agree that one should keep most logic out of the code-behind, I disagree that there should be zero code there.

    View-specific code is ok to have there. That is, code that exists solely to perform a view function, such as building an animation or something, or setting up a relationship between two elements in a view when perhaps that is cumbersome to do in xaml, can be in the view.

    Putting something into a specific visual state in response to a message from the VM is, perhaps, another case. Typically (99%) you’d handle that with binding, but that’s not always a reasonable route to take.

    Other view code could be for things like displaying a file dialog. Displaying a file dialog is really a view function. Dealing with the results of the dialog should happen elsewhere. If not displayed there, you’re stuck doing something like displaying UI from the ViewModel, which is equally bad, if not worse, than having code in the view.

    In practice, most apps will not need code in the code-behind, and most code folks are tempted to put there really shouldn’t be there, but I’d rather not be dogmatic about it :)

    Pete

  2. Reed says:

    Pete,

    First off, I was suggesting that the goal should be to have zero code in the code behind – not necessarily that it is an absolute, hard rule.

    That being said, I do agree that there are times when it’s reasonable to have code in the code-behind. However, in my experience to date, I’ve yet to find a single instance where there wasn’t a more elegant approach. Typically, I’ve found that, when I need code in the code behind file, it’s nearly always handled more elegantly, and more reusably, by creating an attached property or (Expression Blend SDK-based) Behavior, or by using some form of dependency injection/service (I use MEF for this) to handle the creation from within the ViewModel.

    Personally, I think displaying a FileDialog is a function of the ViewModel – not because of the dialog (which I agree is View, but could easily be provided via a service), but because the processing of a file dialog is logic that needs to be tested, and having that as part of a command or a method in the ViewModel makes testing much simpler.

    Anyways, thank you very much for your comments!

    -Reed

  3. Pete says:

    Thanks Reed. I appreciate the clarification.

    I love this series, BTW.

    On file dialog: One test I have mentally for what belongs in a viewmodel is “if I changed view technology, would it still apply”. I agree that a services is probably a better approach there.

    Many Silverlight folks look to WPF thought leaders for information on patterns like MVVM. Until very recently, they had to do things differently due to limitations in the platform. Often times, that meant some small amount of wire-up code in the code-behind. I agree that in WPF it’s harder to justify since the platform is more complete.

    Pete

  4. Reed says:

    Pete,

    Very good point re: Silverlight vs. WPF. I definitely see how the limitations in Silverlight, especially prior to SL 4, would make it so having View related code is “less bad” than the alternative hoops you’d have to jump through to avoid it.

    Mostly, my goal here was to get people coming from Windows Forms (ie: writing desktop apps) to think differently, so I’m really focused on WPF over Silverlight. I’m trying to explain the why behind the pattern, as well as what specifically makes it work in WPF. It’s something I feel has been lacking in all of the (very excellent) MVVM articles I’ve read to date… For a Windows Forms developer, putting code in the code behind is natural – trying to break that habit is probably the most important hurdle to jump through in moving to WPF, in my opinion.

    Thanks for the feedback! I really appreciate it.

    -Reed

  5. Robert says:

    Thanks Reed, this has been an outstanding series of articles on a subject I find quite fascinating. I’ll be following along for more.

  6. zamesking says:

    Great stuff, I got time to read your mvvm articles after my vocation. reed, I got a problem at hand now, I can not find an elegant solution for how to two-way bind the selectedItems in ListBox to the datasource in my viewmodel. Did you have any suggestions?

  7. Reed says:

    zamesking,

    Here’s an article describing one approach. Using SelectedItems is tricky, though.

    http://bit.ly/alNF72

    -Reed

    • zamesking says:

      Reed,

      Thanks for the reply, but I can not open the link in my country. Would you please copy the text, and send it to my mail box?

Trackbacks

Check out what others are saying about this post...
  1. [...] This post was mentioned on Twitter by Reed Copsey, Jr., Caspar Kleijne. Caspar Kleijne said: RT @ReedCopsey: Blogging about moving from WinForms to #WPF with #MVVM in #csharp – Part 7, MVVM, is online: http://bit.ly/8cqsT1 [...]

    [WORDPRESS HASHCASH] The comment’s server IP (208.74.66.43) doesn’t match the comment’s URL host IP (74.112.128.10) and so is spam.

  2. [...] Windows Presentation Foundation provides us with new opportunities to build applications that are very flexible to design, easy to maintain, and clear to understand.  By taking advantage of Data Binding, Commands, and Templating, we can rethink the way we build our applications, and design them using the Model-View-ViewModel Pattern. [...]



Speak Your Mind

Tell us what you're thinking...
and oh, if you want a pic to show with your comment, go get a gravatar!