MVVM (Model/View/ViewModel) is an architectural pattern that is well-suited for Silverlight and WPF development. It is a variation of the MVC pattern that originated from the development of Expression Blend.
At its heart, MVVM imposes three kinds of classes that separate out ideas of presentation (Views), logic (ViewModels) and data (Models). Some of the advantages of structuring a project this way: (i) it facilitates code separation, which helps testability and helps you focus your classes on a specific role; (ii) it supports well the data binding architecture of Silverlight and WPF; (iii) it enables designers and developers to collaborate on a project with minimal overhead. (iv) it is a consistent, maintainable, well-understood pattern; (v) it scales well from small to large applications.
Let’s take a look at each of the components of MVVM in a little more detail:
As shown in the diagram above, the ViewModel is the DataContext for the View, and that is how it gets data and commands. In general you should try and move as much code as possible out of the View and into the ViewModel – this makes it easier to unit test the code through the use of mock objects. The Model is fairly straightforward: the main step you need to take is to implement the INotifyPropertyChanged interface to provide a notification that the data has changed. Lastly, there are various techniques for binding the View to the ViewModel: in this session you’ll see them being bound with a ViewModelLocator.
What happens after you want to display data? For example, what if you want to perform some action based on a UI interaction? This is where commands and behaviors come in.
A command is something you can fire based on a user action that starts an event in the ViewModel. It uses a binding syntax to do that. Any control that derives from ButtonBase will let you bind a command directly to it. In the ViewModel you can create your own instance of ICommand (a good recipe for this is RelayCommand from the MVVM Light toolkit) to handle the event.
For other actions where a command isn’t possible (for example, a ListBox item selection), you can use a behavior. Some good pre-built options include EventToCommand (again from MVVM Light) or InvokeCommandAction (from Blend 4’s Interactivity DLL).
As we’ve seen the primary role of the ViewModel is to perform tasks: GetBook, SaveToStorage, NavigateTo etc. However, as this becomes more complex, the ViewModel starts to include code to call web services, access third-party libraries, etc. It starts to make sense to create a separate service class that separates out this helper code and makes it available across multiple ViewModels.
So services provide related tasks to the caller, and are passed through the constructor using dependency injection (passing the class into the constructor as an interface). This abstraction makes the service very testable and easy to write, and keeps a clear delineation between the task and its physical execution on the disk or network.
This is a topic that is sometimes neglected. A lot of the code in your application won’t run at design-time, because the designer can’t be waiting for a web service to return before it shows anything on screen. Design-time data ensures that you can see a fully-populated view of the UI when you’re developing or designing the application. Without some data, it’s almost impossible to style an application, or for that matter, to ensure that the bindings are right.
One way to provide design-time data is to use sample data (Expression Blend makes this relatively easy); another approach is to use design-time services. A proposed approach to this is to use a ServiceProvider, which is one line of code that automatically switches between design-time and run-time service code as appropriate.
The big question to answer with a child window: should you create a separate ViewModel, or use the parent’s ViewModel? Like most architectural questions, the answer is “it depends”. In some cases, the child window is deeply related to the parent child and is essentially an extension of the parent; in other cases, it’s really an unrelated screen. Depending on how you’re using the child window, either approach may be the appropriate.
One note: a child window doesn’t inherit the DataContext from its parent, so you either need to pass the ViewModel through the constructor or have the child window find the ViewModel it needs.
How should the child window be displayed? You can do this in many ways – often a delegated service is an appropriate choice. As a suitable pattern, we can use messaging to handle this.
Messages are events that provide a loosely-coupled model between the ViewModel and the child window. The process is usually triggered by a user action, which initiates a command to the ViewModel. If there is some business logic that needs to be run to determine whether to display the child window or not, that should be in the ViewModel. Then a message is used to send the request to display the window – either to a service or directly to the view. Some popular choices for the message pattern include the EventAggregator from PRISM and the Messenger class from MVVM Light.
RIA Services is very helpful in these kinds of applications: it takes care of managing change tracking for entities, provides methods for saving and reading data, generates entities and models, handles data validation.
With RIA Services, you create your Domain Services as you normally do; you can use the Entities as your models (they already implement INotifyPropertyChanged), and you get a DomainContext object that acts as a gateway to your services and provides change tracking.
For more on Silverlight, check out Silverlight TV and the upcoming Silverlight Firestarter event on December 2nd. Laurent Bugnion���s MVVM Light Toolkit is available here.
[Session CD50 | presented by John Papa]
So Tim, will HTML5 be seeing similar development features that it's strategic?
Hi Joe, thanks for the comment.
There are several current and emerging HTML-based solutions for rich databound applications.
The first one that springs to mind is of course ASP.NET MVC, which delivers the web-based equivalent to MVVM; as mentioned in the notes above, MVVM is really a variant of MVC that is optimized for a XAML-based architecture. The ASP.NET MVC Music Store sample application is not dissimilar to the book scenario that John presents in his session. ASP.NET MVC is architecturally a server-side framework, of course, although in combination with the AJAX Control Toolkit it can generate pretty rich apps that spread the workload across client and server.
For a more client-centric approach, jQuery is rapidly adding rich data-centric capabilities. In fact, Scott Guthrie's team built some powerful templating and data binding extensions that we contributed to the jQuery team and are now officially released as plugins. You can see a quick review at the Ajaxian blog, here:
Neither of these frameworks map 1:1 to PRISM or MVVM Light, but they provide important components; over time I'm sure the same level of architectural rigor will be developed for HTML-based enterprise applications. For now, Silverlight remains a solid, mature and powerful choice for this scenario.
Best wishes, Tim
To be clear, that's why I closed my comment by saying that for now, Silverlight is the solid / mature / powerful choice for large-scale RIA apps. In fact, we often come across customer projects where Silverlight isn't powerful enough and where they are using WPF instead because of the greater richness of the data binding architecture and other parts of the framework.
Everything has its purpose - and Silverlight still has plenty of purpose!
Agreed, it is a tiered client platform and Microsoft cannot ignore HTML5. The problem is that WPF is largely a superset of Silverlight. The switch to the next tier - or supporting multiple tiers is easy(ish). If you hit the limit with HTML5 then moving up to Silverlight is a rewrite.
Tim - just an FYI - kind of ironic.
But you site doesn't render properly on ie9 beta1, but it works fine in Chrome. ie9 crops the bottom.
Yes - it's very frustrating and a bitter irony. It's because the blog software MSDN uses is explicitly forces the browser into IE7 compatibility mode with the following meta tag:
<meta http-equiv="X-UA-Compatible" content="IE=7" />
I'm not sure why it includes this - I'll have to investigate. If you press F12 and set the document mode to "IE9 standards", then the site works as expected.
Just a little thing - & I'm probably being fussy, but...
"over time I'm sure the same level of architectural rigor will be developed for HTML-based enterprise applications"
I'd suggest that at least as great levels of architectural rigour have been available (and practiced) with HTML enterprise applications, but for longer. That's why working with web/HTML technologies is often far more productive, especially outside of the Microsoft community which still suffers from a legacy of not 'getting' the web.
I'd challenge that "Silverlight is the solid / mature / powerful choice for large-scale RIA apps". I think that, like Flash, there are edge cases where its use may be justified - media streaming, graphic intensive applications (charts, games) - but on the whole the vast bulk of RIA use cases can met more than satisfactorily through the application of standard web technologies which are far more ubiquitous and can offer greater levels of productivity & lower costs of ownership over time.
"In fact, we often come across customer projects where Silverlight isn't powerful enough and where they are using WPF instead "
This I completely agree with, in you're deploying an application into a space where you can control/dictate the environment (eg Windows) then why use Silverlight? As it stands WPF represents a far more powerful tool for applications.
All of that fussyness about the comments aside, I liked the article. I tend to treat the ViewModel more as a Gateway to the Model than gluing it to the view as such. A bit like the use of ViewModels (different I know) in an MVC context where the domain model itself is not known by the View, but a separate View specific model mediates between the two acting as an anticorruption layer protecting the view specific concerns from permeating the domain model (though of course it's horses for courses & in some cases this extra layer of abstraction will be unnecessary).
Hey Tim, not relevant to the topic but I loved your diagrams.
What do you use to create this? Also what's the font that looks like comic sans?
Hi Merill, John Papa (the session author) really deserves the bulk of the credit for the diagram. All I did was a little reformatting work to repurpose it from a PowerPoint slide into a suitable web graphic.
The script font is Buxton Sketch, created by the Ascender foundry and named in honor of Bill Buxton. It's installed with Expression Blend and is used as part of the "sketchy styles" for SketchFlow, the UI prototyping tool that's included.
Sweet. Thanks a lot for replying. Cheers
Neil - could you expand on your point?
What frameworks do you use in HTML to do MVVM, rich two-way databinding?
How would you reskin an HTML page to change the look completely? I realize that JQuery now has limited support for DataTemplates - is this what you're using?
Can you bootstrap the controls like Silverlight/WPF does so that everything is rendered down to a set of primitives?
What about IoC and support for large projects? How do you describe the SoC for a good clean architecture?
for another opinion on MVVM have a look at: