This topic provides an overview of the MVVM pattern, its terminology, concepts and benefits, as well as describing how ClientUI supports the MVVM pattern throughout its entire framework and controls. It also includes the examples of using MVVM in several key scenarios as well as links to advanced walkthroughs.
MVVM: The Basics
Model-View-ViewModel (further referred as MVVM) is an architectural pattern used in software engineering that originated from Microsoft as a specialization of the Presentation Model design pattern. The MVVM pattern is targeted at modern UI development platforms that originally invented in Windows Foundation Presentation (WPF) and later adopted in Silverlight.
In its fundamental design concept, MVVM makes use of specific functions in Silverlight such as bindings, data context and visual tree model to better facilitate the separation of view layer development from the rest of the pattern by removing virtually all “code behind” from the view layer. Instead of requiring UX designers to write the view code, they can use the native XAML markup language and create bindings to the ViewModel, which is written and maintained by application developers. This separation of roles allows UX designers to focus on the user experience needs rather than programming or business logic, allowing for the layers of an application to be developed in multiple work streams.
The following illustration describes the main components of a Silverlight/WPF application that uses MVVM pattern. The View, ViewModel and Model layer are highlighted in the dotted line rectangle to show you the roles and scope of the MVVM pattern in a typical page.
The following sections explain the concept of each layer described in the above illustration.
The View layer is the user interface of your application which mainly consisted of layout and user interface controls written in XAML markup. The View layer often includes resources that required in the user interface, such as data templates and styles.
The Model layer refers to the entities, business objects, data source, proxy objects and other repositories available in your application. The Model should be designed in a way that it does not know the existence of the View or the ViewModel. This means that the model should not access, reference or interact directly with the ViewModel or the View.
The ViewModel layer describes the user interaction logic of the view by exposing the properties such as commands, observable commands and selection objects that can be bound from the view. In most cases, the ViewModel encapsulates the Model and expose it as properties that can be referenced from the View. The ViewModel also contains methods that perform validation and certain business logic which is invoked by the command initiated from the View. Note that the ViewModel should be designed in a way that it does not know the existence of the View. This means that the ViewModel should not access, reference or interact directly with the View.
The benefits, examples and walkthroughs of using MVVM pattern with the ClientUI framework and controls are explained later in this topic.
Why Use MVVM?
In short, the Model-View-ViewModel pattern is a simple and effective set of guidelines for designing and implementing a Silverlight/WPF application. It allows you to create a strong separation between data, behavior, and presentation, making it easier to control the software development process primarily on the user interface engineering.
The MVVM pattern introduces a number of advantages over the classic ViewModel pattern, such as:
- Loosely coupled architecture. The MVVM pattern promotes a design pattern that emphasizes the separation of concerns between view, user interaction logic, behaviors and model. Applications built with such loosely coupled architecture often result in rock-solid stability with less issues.
- Maintainable and extensible code. With MVVM pattern, your code is more maintainable and easy to extend. This is made possible because your project is generally separated into layers thus enables you to enhance specific parts without affecting the others.
- Testable code. The MVVM pattern allows your code to be consistently tested through unit testing. It is possible to unit test only certain functions in the layers, thanks to the great separation concept introduced by MVVM.
- Manageable development process. With the UI (View) separated from the user interaction logic, designers can focus on the user interface and experience aspects of the application, while developers can focus on the model, entities and business logic in a parallel work stream.
MVVM Support in ClientUI
In the previous sections, you have learned the basic concepts and benefits of using MVVM pattern in your application development. This section describes how ClientUI supports the MVVM pattern in an end-to-end approach throughout its frameworks and user interface controls.
One of the fundamental pillars that makes MVVM a powerful pattern is the commanding model originally introduced in WPF. A command can be declaratively defined in the XAML while its logic is separated to another class, which can be the code behind of the view or a ViewModel class. This concept aligns with the MVVM fundamental whereby the user interaction logic of a view should be loosely coupled from the View layer.
ClientUI provides a comprehensive commanding framework to facilitate the application development using MVVM pattern that works in both Silverlight and WPF project. The commanding framework is engineered with the commanding infrastructure, behaviors and specifications of WPF. As the result, you can now take advantage of commanding in a Silverlight project that will also work in WPF. This unification process is often referred as unified development model. For more information on how ClientUI promotes unified development model in Silverlight and WPF, see Unified Development Model.
The commanding framework in ClientUI introduces a number of commands that specifically designed for MVVM pattern such as DelegateCommand and HybridDelegateCommand. The DelegateCommand allows you to define the commands in the ViewModel and write the event handler for the delegates in the ViewModel as well, thus eliminates the need to reference the event handler directly in the View or code behind of the View. To learn more about the commanding concept, see Commanding Overview.
The following example shows how a DelegateCommand is configured in an MVVM pattern implementation.
More complete examples and walkthroughs for implementing MVVM pattern are available later in this topic.
ClientUI provides a variety of frameworks that supports MVVM pattern such as the ItemTemplateSelector and ItemContainerStyleSelector implemented in the framework level that powers the entire user interface controls in the ClientUI. The selector enables you to define the data templates and styles in the XAML while keeping the selector logic separated. The data templates and styles make MVVM pattern more usable by taking advantage the powerful XAML binding engine which automatically locate and apply those templates and styles at run time.
The following example shows how to configure a UXListBox to show customized item template that defined in XAML to be based on the alternating row logic that written in selector logic class.
While the commanding and frameworks are essential MVVM's building blocks, the lacking of UI controls that support MVVM semantics can create difficulty and unnecessary complexity in implementing MVVM pattern in your application. For instance, a DialogBox control that does not support MVVM semantics will require developers to write plumbing code, a number of interfaces and proxy implementation to workaround the limitation.
ClientUI shipped with over 120 rich presentation controls that completely support MVVM pattern. All controls in ClientUI are thoughtfully engineered in a way that expose bindable properties for features that are likely consumed in the view model, particularly selection related properties, property bindings, items source, busy state management, and more.
For instances, consider an advanced control such as CoverFlow that shows a list of contacts. As users flipped to the next item, the contact details should be reflected accordingly. Using UXFlow that fully supports MVVM, you can handle the item presentation and selection entirely in XAML. The following example shows how to setup the UXFlow to achieve the scenario described in the example.
For more walkthroughs on using ClientUI controls with MVVM pattern, see MVVM Pattern Walkthroughs.
Base Classes and Templates
To help you quickly get started with MVVM pattern application development, ClientUI provides a number of MVVM-ready project templates that integrate to Visual Studio 2010.
The basic MVVM project templates include base classes such as ModelBase.cs and ViewModelBase.cs as well as several providers to work with dialog boxes in ClientUI. Some advanced MVVM business templates include more comprehensive base classes such as ValidationViewModelBase.cs and EntityValidationViewModelBase.cs to provide built-in error validation that integrates with data annotations in the domain service.
The following illustration shows the installed ClientUI project templates.
For more information about the available project templates in ClientUI, see Introduction to ClientUI Project Templates.
This section provides the code examples of using MVVM pattern in several common scenarios.
Before you can write code that leverage MVVM pattern, it is best practice to create several base classes implementing the interfaces and members that are commonly used in the MVVM classes.
The following example shows the base class for a simple Model class.
As shown in the above code, the ModelBase class generally implements two interfaces, the INotifyPropertyChanged and IDataErrorInfo. This implementation has been updated to use the new interfaces available in Silverlight 4 and WPF 4. The INotifyPropertyChanged is one of the fundamental interfaces in Silverlight/WPF that enables the binding engine to perform two-ways data binding, that is, changes in the model can be propagated to the target that bound to that particular model. The IDataErrorInfo provides built-in error validation that generally notifies an error to the binding engine.
The following example shows the base class for a simple ViewModel class.
The ViewModelBase class is straightforward where it implements a single INotifyPropertyChanged interface. This simple base class for ViewModel is already sufficient to leverage the MVVM pattern which are explained in the following examples.
BookModel, BookViewModel and BooksViewModel
Once the base classes are created as described in the previous sections, you can start to create the MVVM classes for your scenario. This example uses book scenario where MVVM pattern will be used to load the books data source from xml and show the selected book to the view.
The following code shows the complete listing for the BookModel.
The following code shows the complete listing for the BookViewModel. The BookViewModel describes the view for a book and also exposes several properties that can be useful for binding in the View layer.
The following example shows a simple code listing for the BooksViewModel. Notice the the BooksViewModel is derived from ViewModelBase class. The simplest view model for showing a list of items often contain a property with ObservableCollection<T> type to represent the collection of the items.
One of the most common scenarios in MVVM pattern is to have a reference to the selected item in the view. This basic state management enables the user interaction logic to be written entirely in the ViewModel which is useful to perform validation and maintaining the state of other properties in the ViewModel. For an instance, you may want to set the Save command's CanExecute to false when there are no books selected in the View.
The following example shows how to add a selection property to the BookViewModel.
Loading Books from XML Datasource
In the MVVM pattern, the data loading process is typically performed in the ViewModel layer rather than in the Model layer. Alternatively, the data loading process can also be performed in a Controller layer that statically maintains the data operation. In most cases, it is generally recommended to load data in the ViewModel layer such as described in this section.
The following example shows how to load the book list from an XML datasource embedded in the project. A new Book model is created for each book data and then added to the collection in the ViewModel class.
Buttons and Commanding
Finally, a basic component of an application is to have buttons that execute certain logics based on the selection and input fields.
The following example shows how to add a ShowDetails command to the BooksViewModel and write the event handlers to implement the delegate for the command.
Instantiating the BooksViewModel
Once the BooksViewModel is ready, you create a new instance of the BooksViewModel and bind it to the UI elements within your View.
The following example shows how to instantiate the BooksViewModel and bind it to the UI element to display the book data.
Several points to note in the above example are:
- The ViewModels namespace needs to be declared prior to defining it in the Resources.
- The BooksViewModel is instantiated in the Resources of root control which is the UXPage. You can define it in any nodes of the visual tree as long as the bindings that consume the view model are defined within the children of the particular node.
- Once the ViewModel is defined in the Resources, you assign it to the DataContext of the panel that generally contains the UI elements of which the view model will be bound to. Also remember to refer the view model instance in the resource using a StaticResource markup.
To learn more about advanced MVVM topics, see Advanced MVVM.
To get started using MVVM pattern in your project, see the walkthroughs in the list below.
- Walkthrough: Create Your First ClientUI Application Using MVVM Pattern
- Walkthrough: Create Basic Navigation Application Using MVVM Pattern
- Walkthrough: Create Line-of-Business Navigation Application Using MVVM Pattern
- Walkthrough: Create Rich Application Using Windowing and MVVM Pattern
For more walkthroughs on implementing MVVM pattern, see MVVM Pattern Walkthroughs.