Understanding Model-View-ViewModel is the first step in using it.
Want to make Model-View-ViewModel (MVVM) simple? I know I do. First, I want to explain why I think MVVM appears complicated to many folks, when I think it's quite the opposite. In fact, I think MVVM can prove more valuable that not using MVVM in almost any situation. But for that to happen, first we have to understand what MVVM is and is not.
While very popular, the MVVM pattern is often misunderstood. Sometimes people lump commanding, behaviors, messaging, service locators and other technology features into MVVM. While these are powerful and great features, they're not MVVM; they're helpers you can choose to use with MVVM.
Am I nitpicking? I don't think so. Consider it this way: Can you use MVVM without these features? Absolutely.
Another confusion point is with the frameworks surrounding MVVM. Some I'm very familiar with include PRISM, MVVM Light Toolkit, Caliburn Micro and Cinch. While these frameworks and toolkits are widely used and can prove very valuable, they're not essential for MVVM. Once you clear aside what is not in fact part of MVVM, the rest becomes much clearer.
Once you weed out all the helpers, the essential aspects of MVVM remain: The Model, the View and the ViewModel (what I sometimes call the triad). OK, so that may sound a little anticlimactic, but I can't help if it's true. MVVM is defined by the separation of the Model from the View from the ViewModel. This separation pattern clearly delineates the responsibilities of each of the triad members.
The Model contains the data points that the application requires. Sometimes this comes from a WCF service, a RESTful service, or data aggregated from many places. Where the data comes from is irrelevant. What's important is that the data is pulled into the client and stored in the Model. For example, if building a Twitter client, you may have a set of Model classes for User, Tweet, and Tweets. These classes (sometimes known as domain objects) may be collection classes or single entity classes. The main responsibility of a Model is to describe the data required by the client. Thus a Model is born.
[Click on image for larger view.]
|Figure 1. Flow in Model-View-ViewModel.
The View is the friendly presentation of information to the user. A View may include themes, styles, controls, bindings, events, and other interactions on the screen. The View's responsibility is to keep all presentation in a single place, unencumbered by logic and other heavier code. Often the View will have controls that will map to one or more Model's data points. (In Silverlight, Windows Phone and WPF these controls often map declaratively through data binding XAML markup.)
The ViewModel is the glue between the View and the Model(s). The ViewModel is also known as the "View's Model" because it exposes public properties intended for the View. Often the ViewModel aggregates one or more Models and exposes them to the View as public properties.
The ViewModel is intended for the View, so aggregating the Models in the ViewModel allows the same Models to be reused by many ViewModels (and thus by many Views). Abstraction and aggregation of Models is just one aspect of a ViewModel, however.
Sometimes a View may require a data point not in any Model. This might be a UI-specific property like IsBusy for a ProgressBar control, or some calculated property using logic. These View-specific data points can be created in the ViewModel as public properties without muddying the Models. This is abstraction and separation at its core.
But that's not all a ViewModel does. As I mentioned, a ViewModel is the glue between the View and the Model. Because XAML has a great binding story, MVVM really shines. The View's DataContext is set to an instance of a ViewModel class. This gives the View access to all the public properties in the ViewModel.
There are other variants and extensions of what the members of the MVVM triad can do. For example, does the ViewModel go get the data and load the Model(s), or do the Model(s) know how to load themselves? (I highly recommend and prefer the former.)
Whatever your choice, it's still MVVM. You can also debate methods to bind the View to the ViewModel. Whether you do it in XAML, the codebehind, the ViewModel or in a third-party class (what I call the marriage between View and ViewModel), its still MVVM. My point here is that you and your developer colleagues may deviate and differ on how to implement MVVM, but at its core MVVM is just the separation of the MVVM members. In my next blog entry, I'll provide some brief code examples to illustrate this separation.