Tuesday, June 12, 2012

Model View ViewModel


Model View ViewModel (MVVM)


1)      Introduction
2)      What's the difference between MVVM, MVP and MVC?
 2.1)  MVC - Model-View-Controller:-
 2.2) MVP - Model-View-Presenter
 2.3) MVVM - Model-View-ViewModel
3)       DataModel
4)       ViewModel
5)       View
6)       Code Snippet
7)       Separation of logic and presentation
8)       How the MVVM pattern became convenient
9)       Advantages of MVVM
10)   Some MVVM Frameworks
 


1)      Introduction:-
The Model View ViewModel (MVVM) sometimes called DataModel-View-ViewModel is an architectural pattern Very similar to Martin Fowler’s “Presentation Model”. It is first published by John Gossman of MSFT, Dan Crevier of MSFT wrote a multi-part series for MVVM.
MVVM is targeted at modern UI development platforms (Windows Presentation Foundation or WPF, and Silverlight).

2)      What's the difference between MVVM, MVP and MVC?
2.1) MVC - Model-View-Controller:-
MVC is a well-established pattern made up of the “Mediator” and the “Observer” patterns.  The MVC pattern consists of one controller that directly gets all user input. Depending of the kind of input, he shows up a different view or modifies the data in the model. The view sits at the top of the architecture. The controller sits below the view. The model sits below the controller. The model and the view are created by the controller. The view only knows about the model, but the model does not know about any other objects.

2.2) MVP - Model-View-Presenter
In the MVP pattern, controller is replaced with a presenter. The view gets the user input and forwards it to the presenter. The presenter than modifies the view or the model depending on the type of user action. The view and the presenter are tightly coupled. There is a bidirectional one-to-one relation between them. The model does not know about the presenter. The view itself is passive, that’s why it's called presenter pattern, since the presenter pushes the data into the view. This pattern is often seen in Win Forms and early WPF applications.

2.3) MVVM - Model-View-ViewModel
The model-view-viewmodel is a typically WPF pattern. The controller is replaced with a view model. The view model sits below the UI layer that gets all the user input and forwards it to the viewmodel. The view model exposes the data and command objects that the view needs. The view actively pulls the data from the viewmodel by using databinding. The model does not know about the view model.

 
  Basic diagram                 

Detail Diagram









3)      DataModel
DataModel is responsible for exposing data in a way that is easily consumable by WPF. All of its public APIs must be called on the UI thread only. It must implement INotifyPropertyChanged and/or INotifyCollectionChanged as appropriate. When data is expensive to fetch, it abstracts away the expensive operations, never blocking the UI thread. It also keeps the data “live” and can be used to combine data from multiple sources. These sorts of classes are fairly straightforward to unit test.
The lines between DataModels and ViewModels can be blurry. DataModels are often shown in the UI with some DataTemplate, which isn’t really so different than the way we use ViewModels. However, the distinction usually makes sense in practice. I also want to point out that there’s often composition at many layers. ViewModels may compose other ViewModels and DataModels. And, DataModels may be composed of other DataModels.

4)      ViewModel
A ViewModel is a model for a view in the application. It exposes data relevant to the view and exposes the behaviors for the views, usually with Commands. The model is fairly specific to a view in the application, but does not subclass from any WPF classes or make assumptions about the UI that will be bound to it. Since they are separate from the actual UI, these classes are also relatively straightforward to unit test.
The ViewModel is a model of the view. That means: You want to DataBind a property from
your DataObject (model) to a property from your ViewObject (view) but you sometimes cannot bind directly to a CLR property of the model (because of converting or calculating). This is when ViewModel comes into play. It propagates the already calculated or converted value from your model, so you can bind this property directly to the view property.


5)      View
A View is the actual UI behind a view in the application. The pattern we use is to set the DataContext of a view to its ViewModel. This makes it easy to get to the ViewModel through binding. It also matches the DataTemplate/Data pattern of WPF. Ideally, the view can be implemented purely as Xaml with no code behind. The attached property trick comes in very handy for this.
The main thrust of the Model/View/ViewModel architecture seems to be that on top of the data (“the Model”), there’s another layer of non-visual components (“the ViewModel”) that map the concepts of the data more closely to the concepts of the view of the data (“the View”). It’s the ViewModel that the View binds to, not the Model directly.



6)      Code Snippet:-

View:-

<Window x:Class="WpfSimple.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfSimple"
        Title="MainWindow" Height="150" Width="370">
    <Window.DataContext>
        <local:MainWindowViewModel/>
    </Window.DataContext>
        <Grid>
        <Button Content="Click"
                Height="23"
                HorizontalAlignment="Left"
                Margin="77,45,0,0"
                Name="btnClick"
                VerticalAlignment="Top"
                Width="203"
                Command="{Binding ButtonCommand}"
                CommandParameter="Hai" />
    </Grid>
</Window>

The ViewModel :-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Windows;

namespace WpfSimple
{
    class MainWindowViewModel
    {
        private ICommand m_ButtonCommand;
        public ICommand ButtonCommand
        {
            get
            {
                return m_ButtonCommand;
            }
            set
            {
                m_ButtonCommand = value;
            }
        }
        public MainWindowViewModel()
        {
            ButtonCommand=new RelayCommand(new Action<object>(ShowMessage));
        }
        public void ShowMessage(object obj)
        {
            MessageBox.Show(obj.ToString());
        }
    }
}

RelayCommand
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;

namespace WpfSimple
{
    class RelayCommand : ICommand
    {
        private Action<object> _action;
        public RelayCommand(Action<object> action)
        {
            _action = action;
        }
        #region ICommand Members
        public bool CanExecute(object parameter)
        {
            return true;
        }
        public event EventHandler CanExecuteChanged;
        public void Execute(object parameter)
        {
            if (parameter != null)
            {
                _action(parameter);
            }
            else
            {
                _action("Hello World");
            }
        }
        #endregion
    }
}
INotifyPropertyChanged
public class Product:INotifyPropertyChanged
{
    private int m_ID;
    private string m_Name;
    private double m_Price;
    #region INotifyPropertyChanged Members
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion

    public int ID
    {
        get
        {
            return m_ID;
        }
        set
        {
            m_ID = value;
            OnPropertyChanged("ID");
        }
    }
    public string Name
    {
        get
        {
            return m_Name;
        }
        set
        {
            m_Name = value;
            OnPropertyChanged("Name");
        }
    }
    public double Price
    {
        get
        {
            return m_Price;
        }
        set
        {
            m_Price = value;
            OnPropertyChanged("Price");
        }
    }
}

class ProductViewModel
{
    private IList<Product> m_Products;
    public ProductViewModel()
    {
        m_Products = new List<Product>
        {
            new Product {ID=1, Name ="Pro1", Price=10},
            new Product{ID=2, Name="BAse2", Price=12}
        };
    }
    public IList<Product> Products
    {
        get
        {
            return m_Products;
        }
        set
        {
            m_Products = value;
        }
    }
    private ICommand mUpdater;
    public ICommand UpdateCommand
    {
        get
        {
            if (mUpdater == null)
                mUpdater = new Updater();
            return mUpdater;
        }
        set
        {
            mUpdater = value;
        }
    }
    private class Updater : ICommand
    {
        #region ICommand Members
        public bool CanExecute(object parameter)
        {
            return true;
        }
        public event EventHandler CanExecuteChanged;
        public void Execute(object parameter)
        {
        }
        #endregion
    }
}
Main Window (View)
<Window x:Class="WpfMvvmTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid Height="314">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <ListView Name="ListViewEmployeeDetails" Grid.Row="1" Margin="4,109,12,23"  ItemsSource="{Binding Products}"  >
            <ListView.View>
                <GridView x:Name="grdTest">
                    <GridViewColumn Header="ID" DisplayMemberBinding="{Binding ID}"  Width="100"/>
                    <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"  Width="100" />
                    <GridViewColumn Header="Price" DisplayMemberBinding="{Binding Price}" Width="100" />
                </GridView>
            </ListView.View>
        </ListView>
        <TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,7,0,0" Name="txtID" VerticalAlignment="Top" Width="178" Text="
Binding ElementName=ListViewEmployeeDetails,Path=SelectedItem.ID}" />
        <TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,35,0,0" Name="txtName" VerticalAlignment="Top" Width="178" Text="{Binding ElementName=ListViewEmployeeDetails,Path=SelectedItem.Name}" />
        <TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,61,0,0" Name="txtPrice" VerticalAlignment="Top" Width="178" Text="{Binding ElementName=ListViewEmployeeDetails,Path=SelectedItem.Price}" />
        <Label Content="ID" Grid.Row="1" HorizontalAlignment="Left" Margin="12,12,0,274" Name="label1" />
        <Label Content="Price" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="12,59,0,0" Name="label2" VerticalAlignment="Top" />
        <Label Content="Name" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="12,35,0,0" Name="label3" VerticalAlignment="Top" />
        <Button Content="Update" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="310,40,0,0" Name="btnUpdate"
                VerticalAlignment="Top" Width="141"
                Command="{Binding Path=UpdateCommad}"
                />
    </Grid>
</Window>


7)      Separation of logic and presentation: -
 The MVVM pattern is so far only a convenient way to bind data to the view. But what about user actions, how are they handled? The classic approach, known from WinForms is to register an event handler that is implemented in the code-behind file of the view. Doing this has some disadvantages:
Having event handlers in the code-behind is bad for testing, since you cannot mock away the view.
Changing the design of the view often also requires changes in the code, since every element has its different event handlers.
The logic is tightly bound to the view. It's not possible to reuse the logic in another view
So the idea is to move the whole presentation logic to the view model by using another feature of WPF, namely Commands. Commands can be bound like data and are supported by many elements as buttons, togglebuttons, menuitems, checkboxes and inputbindings. The goal here is not to have any line of logic in the code-behind of a view.
8)      How the MVVM pattern became convenient
WPF has a very powerful databinding feature that provides an easy one-way or two-way synchronization of properties. You can directly bind two WPF elements together, but the common use of databinding is to bind some kind of data to the view. This is done by using the DataContext property. Since the DataContext property is marked as inherited, it can be set on the root element of a view and its value is inherited to all subjacent elements of the view.
One big limitation of using the DataContext property as data source is, that there is only one of it. But in a real life project you usually have more than one data object per view. So what can we do? The most obvious approach is to aggregate all data objects into one single object that exposes the aggregated data as properties and that can be bound to the DataContext. This object is called the view model.


9)      Advantages of MVVM :-
The view-model can easily be tested by using standard unit-tests (instead of UI-testing)
The view can be redesigned without changing the viewmodel, because the interface stays the same.
The view-model can even be reused, in some special cases (this is usually not recommended)




10)   Some MVVM Frameworks
PRISM (Microsoft)
MVVM Light (Laurent Bugnion)
WPF Application Framework
Chinch
Caliburn Micro
Onyx
nRoute
MVVM Foundation


10.1) Prism:-
Prism (or Composite WPF) is a framework provided by Microsoft to help build composite WPF and Silverlight applications. It has mechanisms for UI composition, module management and dependency injection. Prism itself is modular, so you can pick and choose the parts of it that are relevant to your application.
For more information about Prism see http://compositewpf.codeplex.com/.
10.2) MVVM Light (Laurent Bugnion)
Like other MVVM implementations, the toolkit helps you to separate your View from your Model which creates applications that are cleaner and easier to maintain and extend. It also creates testable applications and allows you to have a much thinner user interface layer.
For more information about MVVM Light see http://mvvmlight.codeplex.com/
10.3) WPF Application Framework
The WPF Application Framework (WAF) is a lightweight Framework that helps you to create well-structured WPF Applications. It supports you in applying a Layered Architecture and the Model-View-ViewModel (aka MVVM, M-V-VM, PresentationModel) pattern.
For more information about WAF see http://waf.codeplex.com/



10.4) Chinch
Cinch is a framework that gives a number of helper classes to allow the developer to quickly get to grips with creating scalable testable MVVM frameworks as quickly as possible.
For more information about Chinch see http://cinch.codeplex.com/

10.5) Caliburn Micro
It implements a variety of UI patterns for solving real-world problems. Patterns that are highlighted include MVVM (Presentation Model), MVP and MVC
For more information about Caliburn Micro see http://caliburnmicro.codeplex.com/

10.6) Onyx
Onyx provides a framework that aids in the creation of WPF applications that follow the Model-View-ViewModel design pattern. The goal when developing with Onyx is to create XAML based Views that have no code in the codebehind file (remember, this is a goal, not a requirement, and one should be pragmatic). In addition, the ViewModel should contain no code that ties it to any specific UI or UI features that are not easily unit tested.
For more information about Onyx see http://wpfonyx.codeplex.com/

10.7) nRoute
nRoute is a composite application framework for creating MVVM-style applications in Silverlight, WPF, and Windows Phone 7
For more information about nRoute see http://nroute.codeplex.com/

10.8) MVVM Foundation
MVVM Foundation is a library of classes that are very useful when building applications based on the Model-View-ViewModel philosophy. The library is small and concentrated on providing only the most indispensable tools needed by most MVVM application developers

For more information about MVVM Foundation see http://mvvmfoundation.codeplex.com/


Google