Introducing MVVM with simple gallery example
5 commentaires
Silverlight 4 and Blend 4 RC are barely out that we already see all the profits made by them. Two new features have retained my attention, binding system improvments and the design pattern MVVM fully managed through the implementation of commands. The aim of this post is to familiarize you with the implementation of the design pattern MVVM (Model, View, View-Model) in Silverlight and 4 highlight the benefits of the linkage system.
I - A word on the new link system
As you probably know, it is now possible to use data binding between different instances of DependencyObject. Previously, it was simply impossible to create a binding beetween XAML objects when they didn't inherit from FrameworkElement class. Now, almost everything is "bindable" and that's a good thing. We can therefore create a Binding between a RotationTransform of a RenderTransform and the Value property of a Slider. This example may be useful in design but not really relevant for a developer. We will see the benefits of this improvement in MVVM.
II - Foreword
This article only reflects my own vision of this pattern. There are many interpretations of the design model MVVM. Partly for this reason that the type of project MVVM "MVVM Silverlight Application" that was generated in Blend 4 beta has been renamed Databound Silverlight Application in Blend 4 RC. This allow to not freeze MVVM to one interpretation and at the same time go beyond this type of development.
III - Introduction
MVVM is a principle of design and organization wich split the development of RIAs into three categories : Model, View and View-Model. It's a sub category of separation pattern like MVC or MVP. This way, the code and design of an application are completely separated and it is easier to change them. In practice the developer will provide commands and properties which will be very simple to apply to controls contained in the view.
The direct benefit of this methodology is to free the designer of any constraints on design. Designer will be able to make his own decisions and choices. His tasks will become far more interesting than just skinning component. He will freely define the type of controls, their name, the transitions without having to worry about implementation details.
We will see a practical example of that concept further.
1 - View
A View contains all visual interfaces dedicated to user interactions. In other words, it's the IHM, they are composed of three types of things:
* A visual and logical tree composed of UIElement instances.
* Transitions and animations.
* The logical behavior can, for example, to control animations and transitions.
2 - Does a view should contain code behind ?
Here, 90% of developers say no. For my part, I think that view must contain its own logic to manage animations and transitions. In most cases, these tasks are not handled by the creation of C # code but by using behaviors. Thus, there is no need C # code because the behaviors are fully responsive to this issue. The challenge of design is often due to possible coupling between the data management and display. The behaviors were also intended to address this problem. These are crucial in MVVM Design pattern.
3 - Model
For simplicity, the model contains datas. It also handles all remote calls or transactions corresponding to CRUD operations (Create, Read, Update, Delete). Developers often use a static class to access datas easily. The model can broadcast events as needed to indicate the status of each transaction. Some developers will use model only as storage space. We won't cover Model in this post
4 - View-Model
This is the heart of the MVVM design pattern. Actually, View-Model is an abstraction of View from Model point of view. In other words, View-Model manages the connection between the data contained in the model and their display in the View. Thus the intermediary between View and Model.
I was recently asked:
Is it better to start from the View-Model or View shall be the first step ?
There is no simple answer to this question. This depends primarily on your business and to what kind of quality you want to make the application. Would you get a strong graphical interaction or a clean and efficient architecture with a maximum performance ? Some think that both are possible but again we should not kid ourselves. If one does not impact the other, we would have only one type of project named Databound Application. More graphics and interactions are burdensome, it is difficult to provide a clean and efficient architecture maintaining the same time. I have this point of view because I come from Flash platform. However, when designing an application, it is advisable to start with a prototype. The view is what is most practical for your client and you as a developer. The prototype allows to formalize the application that your client want to obtain, and that is what is most important. In the case of very standard applications such as a video player, for example, it is possible to design View-Model first, as the operations that the user wishes to achieve will always be the same (Play, Stop, Pause, etc ... ). The commands are, in this case, very predictable. We return to the concept of commands later.
5 - Does View-Model has to manage animations and transitions?
If we take the basic definition (View-Model an abstraction of the view), View-Model don't need to trigger transitions and animations directly. It just have to update properties that are bound to View. View can be notified about these updates and will use behaviors will help us in this task. However, in the case of animations created dynamically, it happens that View-Model has to manage the animations. It will in this way create a class dedicated management or use of properties attached outbuildings. Wherever possible, contrary to popular belief, views include the logic to display the transitions and animations, it's what is the code behind the UserControl view. The behaviors are nothing other than logic code placed in the visual tree and logical. It do not inherit from UIElement but DependencyObject. By default, it is the responsibility of interactive designer to trigger animation.
6 - All MVVM ?
The big question is : should you always design everything with MVVM design pattern ? The answer is no. Here are my arguments:
* If it was the case, we wouldn't have different types of projects in Blend.
* Use a single design pattern is extrem. In practice, it does not not always fit the constraints of time allotted.
* Depending on the size of your projects and needs (to evolve and change), it is not necessarily useful to use MVVM as it can in some case, add a touch of complexity. For example, when you try to create binding between read only collections of an object in a View, and collections contained in Model-View.
* Make Full MVVM is primarily dogma, it's like to cooking as Italian dishes. In short, you're missing the French cuisine, Indian, etc ...
* More the design and its constraints are important, the greater it will be difficult to standardize the development. It is the eternal problem of software development. The design and development are two aspects of RIA production.
MOST important, you can implement MVVM in your projects each time you think it will fit. You will get lot of experience in short time that way.
IV - An MVVM Gallery
After this brief introduction, we will immerse ourselves in the design of a complete application in MVVM.
Download GalleryMVVM_base project. This project is based on Silverlight Databound Application. You'll notice first that MainPage.xaml contains a View formalized by a UserControl named GalleryView. So you might considerMainPage as a layout container of Views. A directory contains the UserControl symbolizing the party view, another contains the classes for View-Model, the last one contains all classes later model managing access to data (see Figure below).
In GalleryView.xaml, all objects are already created and appointed, this work can be done independently of the development in C #. After a short concertation, we consider that the developer and the designer have agreed on a number of features listed below:
* Show / hide the interactive object (eg button) Previous Image / Next Image
* Load image Next / Previous
* Getting ImageBrush the new and the old loaded bitmap (this will help to create transitions)
* View pagination
* Show description, title and url of the image being
* Navigate to the state "while loading" or state "loading finished"
* Display a ProgressBar while loading bitmaps.
The developer and the designer have made their job part of the project. The design is finalized, we must now use the model-view abstraction, called GalleryViewModel, as context data view. That way, the gallery will be alive. We will show later GalleryViewModel's logic. Add the namespace xmlns: local = "clr-namespace: GalleryMVVM" within the UserControl root GalleryView. We will declare a new resource type GalleryViewModel as shown below:
Compile the application if needed by ctrl + shift + b, now that we've instantiated the View-Model as a resource, we can easily define it as data context LayoutRoot grid as shown below.
This is not sufficient, it is best to create a data binding that will update the View when View-Model properties are changed. We substitute this expression
by this one :
Now go in the Data panel, select and retain LayoutRoot unfold Data Context. You get a list of properties and commands corresponding to the specifications established between developer and designer (See below).
Regarding the view you're done, just drag and drop, properties and commands on objects of the visual and logical tree. It is also possible to proceed through the use of DataBinding menu. It is obtained when you click on the square icon at the right of each property.

You can do a simple test by dragging and dropping the commands named DisplayNextPicture and DisplayPreviousPicture on buttons. You can also create a DataBinding between Fill property of the Rectangle named newBitmap and NewPictureIB owned by View-Model. As you see, the slide is fully appointed, in other words, the designer can choose the type, layout, names of components and define visual states that he wants to activate. If you want to choose the targeted property where you want to create a Binding, simply press the alt key at the same time as you drag and drop.
V - Manage transitions
The new binding system brought on by Silverlight 4 gives us a lot of flexibility when developing a project following this design pattern. In MVVM, we try to minimize the logic code for each View, so it's pretty convenient to use behavior in Blend to manage transitions and animations.
1 - Trigger transitions
This is one of the major problems when talking MVVM. First, Microsoft provides an interactive behavior named DataStateBehavior that facilitates transition management. You can place it on LayoutRoot, it is able to trigger a transition according to the value of a property of View-Model. In our case, it is a property named IsLoaded that is set to false when the new image is loading, and true when it is loaded. The figure below shows the configuration of behavior.
Specifically, we just have to create a data Binding between Binding property and IsLoaded property of View-Model. When IsLoaded value is equal to True then we displays Completed Visual State otherwise it displays the Visual State named Loading. It may seem strange to put a capital T, but the Value property is typed Object. This methodology has the advantage of giving the designer the task of triggering the transition easily.
2 - Activate or Desactivate Behaviors
In Silverlight 3, it was not possible to bind a property of behavior, as IsEnabled property to another contained by the View-Model. Even if it implements INotifyPropertyChanged, IsEnabled was not "bindable" because the behavior did not inherit from the FrameworkElement but DependencyObject. With the new system of SL4, it is now a thing possible because binding is possible with object wich directly inherit from DependencyObject. Place two instances of behavior GotoStateAction on both copies of a button. When hovering over one or the other, we sail towards the visual state RightButtonMouseOver or LeftButtonMouseOver. When the mouse leaves the button, we will navigate to the state DefaultMouseLeave. The figure below is the setup, however the right button.
In the baseline scenario developer and designer have assumed that the pager (for example: bitmap 1 / 6) is not always diplayed. The paging is activated by View-Model. This happens when the property DisplayPageNumbers (from GalleryViewModel) is set to true.You just have to establish a data binding between IsEnabled (property of behavior) and DisplayPageNumbers. Here is the corresponding XAML :
The code is fairly simple to understand:
* The visibility of the button is linked to RightArrowVisibility of GalleryViewModel.
* The text displayed via the Content property is linked to property Paging of GalleryViewModel.
* Very important, all instances of the type inheriting ButtonBase implement, since Silverlight 4, Commanding via Command property. This allows to execute commands (actions ViewModel). The Click event triggers the commands. For all other types of events click, you can use the behavior named InvokeCommandAction.
* Finally, navigation behaviors are activated or deactivated by the property of DisplayPageNumbers GalleryViewModel.
VI - GalleryViewModel
On-View Model, the developer is on rails. The code is standard and the step are always the same:
* It is quite practical to create a base class which all classes of type View-Model inherit. You can call it ViewModel or ViewModelBase.
* This class must implement two interfaces: INotifyPropertyChanged and IDataErrorInfo. INotifyPropertyChanged can notify the view of any change of properties with DataBinding system. IDataErrorInfo is a new interface provided by Microsoft since SL4. It allows Views to display errors that are thrown. Concretely, this is particularly useful with two way Data Binding. In our case, the interest is lower because the view has no reason to change the properties of view-model. In the case of a form, it is required because IDataErrorInfo is much more convenient than directly throwing exception. You can read the post by John Papa the implementation of IDataErrorInfo.
* It is necessary to create properties that will be accessible directly from the view
* Finally, we must create commands executed from the View. The implementation of commands is also covered by an article by John Papa that you find here. Specifically, it proposes to create an abstract class named DelegateCommand to facilitate the instantiation of commands in view-model.
1 - Les propriétés accessible au sein de la vue "Bindable"
If you want to set a property accessible from the view, it must be declared with the public accessor. Moreover,to use the binding system, it must notify the view when it is changed. To do this, simply use the method NotifyPropertyChanged inherited from class ViewModel. You will find ViewModel class in Tweened.MVVMUtils
2 - Commanding
Commands should always refer to a method and a Boolean value (Boolean indicates whether the command should be executed). The following C # code corresponding to the commands and DisplayNextPicture DisplayPreviousPicture:
The Index property is updated with a new value, and notify the view of this change through the mechanism inherited from INotifyPropertyChanged. The method CanDisplayPictures always returns true which is not ideal, you can do some tests at this level. I only make a test for LoadAllPicture command, the test is made by the CanLoadAllPictures method :
VII - Final Gallery
You can see it here : http://www.tweened.org/wp-content/uploads/applis/diaporamaMVVM/.
You can download source code here : http://www.tweened.org/wp-content/uploads/applis/GalleryMVVM.zip.












[...] le pattern MVVM récemment et grâce à Eric qui a publié un très beau tuto sur le sujet, à lire ici. Je pars d’ailleurs de son exemple pour illustrer la mise en œuvre de l’AOP dans le [...]
Excellent article.
Le modèle M-V-VM serait une autre appellation du modèle MVC (modèle-vue-contrôleur) ?
Excellent article sur le pattern MVVM, approche pragmatique et didactique avec un très bon exemple de gestion de transitions par l’utilisation du DataStateBehavior.
Article à lire et à bookmarker absolument, bravo Eric !
Un article qui intéressera certainement ceux qui se penchent sur MVVM et qui veulent comprendre comment ça marche, en complément à ce billet :
“M-V-VM avec Silverlight, de la théorie à la pratique. ”
adresse : http://www.e-naxos.com/Blog/post.aspx?id=c2053091-cd46-4523-aa37-08ba70e37c23
merci Olivier pour cet info, il y a également cet article plutôt bien pensé :
http://msdn.microsoft.com/fr-fr/magazine/ff798279%28en-us%29.aspx