MVVM In WPF

MVVM is an architecture pattern which facilitates the separation of projects into three logical layers with their own responsibilities. It facilitates modern techiniques such as Separationof Concern, Unit testing, and TDD. It is set of guidelines, that, when used, makes it easier to develop applications.

It is said about MVVM “Use those guidelines when it make sense, and modify them to fit needs of your application at a given point in time."

So, in short, we can say maintenance, extensibility, enabling designer/develops workflow, and taking advantage of WCF/Silverlight databinding are some of the intents of MVVM.

Components of MVVM

MVVM has Model, View, and ViewModel which are explained below,

  • View
    It is a user interface. It is responsible for defining the UI of what the user sees on screen. It is also responsible for taking input from an end user. It is purely defined with XAML and with limited code behind which does not contain business logic. It may or may not have reference to ViewModel. Bindings are activated when the view’s DataContext is set to a class that contains source to the bindings, it is that databinding infrastructure that's build into the WPF/Silverlight that allows designer to create rich and interactive UI. It is not responsible for retrieving data, business logic, business rule and data validation which will be represented to user.

  • Model
    It is the application’s domain model which represents data along with business logic and validation. Its single responsibility is to represent data points. It does not have any reference to View or ViewModel.

  • ViewModel
    It act as link between View and Model. It provided data from model too view, which can be used by View. It contains properties, commands and other abstractions to facilitate communication between View and Model.

Below is a diagrammatical presentation of the association of all three components

MVVM

Advantage of MVVM

  • Reduce Code –behind.
  • Model does not need to change to support View.
  • Designer design, coders code.
  • Reduces development time.
  • Unit Testing.

Disadvantage of MVVM

  • Create more files.
  • Simple Task can be complicated.
  • Lack of Standardization.
  • Specific to WPF /Silverlight Platform.

Now, you can implement MVVM pattern by below approaches in WPF,

  • View-First Approach
    It is a very common method of handling View and ViewModel. In this approach View drives creation and discovery of ViewModel. It binds ViewModle as a resource , locator patter , Unit ,etc.

  • ViewModel-First Approach
    It is also another approach of handling View and VIewModel. In this ViewModel is responsible for creating view and binding itself with View.

Now, let’s look into View-First Approach.

You can achieve View-First Approach by following the below ways,

  • View First in XAML
  • View First in Code-behind

The following example is in XAML,

  1. <UserControl.DataContext>  
  2.     <viewmodel:EmplyeeViewModel/>   
  3. </UserControl.DataContext>  
  • Open Visual Studio.

  • File >> New >> Projects >> Select WPF Project.

  • Now, add Model folder in the Solution.

  • Add Employee Class In Model folder

    1. public class Employee: INotifyPropertyChanged {  
    2.     private string firstName;  
    3.     private string lastName;  
    4.     public string FirstName {  
    5.         get {  
    6.             return firstName;  
    7.         }  
    8.         set {  
    9.             if (firstName != value) {  
    10.                 firstName = value;  
    11.                 RaisePropertyChanged("FirstName");  
    12.                 RaisePropertyChanged("FullName");  
    13.             }  
    14.         }  
    15.     }  
    16.     public string LastName {  
    17.         get {  
    18.             return lastName;  
    19.         }  
    20.         set {  
    21.             if (lastName != value) {  
    22.                 lastName = value;  
    23.                 RaisePropertyChanged("LastName");  
    24.                 RaisePropertyChanged("FullName");  
    25.             }  
    26.         }  
    27.     }  
    28.     public string FullName {  
    29.         get {  
    30.             return firstName + " " + lastName;  
    31.         }  
    32.     }  
    33.     public event PropertyChangedEventHandler PropertyChanged;  
    34.     private void RaisePropertyChanged(string property) {  
    35.         if (PropertyChanged != null) {  
    36.             PropertyChanged(thisnew PropertyChangedEventArgs(property));  
    37.         }  
    38.     }  
    39. }  

  • Now, add ViewModel folder in the Solution

  • Add EomplyeeViewModel class in ViewModel folder.

    1. public class EmplyeeViewModel {  
    2.     public EmplyeeViewModel() {  
    3.         LoadEmployees();  
    4.     }  
    5.     ObservableCollection < Employee > Employees {  
    6.         get;  
    7.         set;  
    8.     }  
    9.     public void LoadEmployees() {  
    10.         ObservableCollection < Employee > employees = new ObservableCollection < Employee > ();  
    11.         employees.Add(new Employee {  
    12.             FirstName = "Mark", LastName = "Allain"  
    13.         });  
    14.         employees.Add(new Employee {  
    15.             FirstName = "Allen", LastName = "Brown"  
    16.         });  
    17.         employees.Add(new Employee {  
    18.             FirstName = "Linda", LastName = "Hamerski"  
    19.         });  
    20.         Employees = employees;  
    21.     }  
    22. }  

  • Now, add View folder in Solution.

  • Add EmployeeView Usercontrol in View and add the below code.

    1. <UserControl x:Class="ViewFirstApproach.View.EmployeeView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:ViewFirstApproach.View" xmlns:viewmodel="clr-namespace:ViewFirstApproach.ViewModel" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300">  
    2.     <UserControl.DataContext>  
    3.         <viewmodel:EmplyeeViewModel/> </UserControl.DataContext>  
    4.     <Grid>  
    5.         <Label>This is Demo</Label>  
    6.         <StackPanel HorizontalAlignment="Left">  
    7.             <ItemsControl ItemsSource="{Binding Path=Employees}">  
    8.                 <ItemsControl.ItemTemplate>  
    9.                     <DataTemplate>  
    10.                         <StackPanel Orientation="Horizontal">  
    11.                             <TextBox Text="{Binding Path=FirstName, Mode=TwoWay }" Width="100" Margin="0 5 3 5"></TextBox>  
    12.                             <TextBox Text="{Binding Path=LastName, Mode=TwoWay }" Width="100" Margin="0 5 3 5"></TextBox>  
    13.                             <TextBox Text="{Binding Path=FullName, Mode=OneWay }" Width="100"></TextBox>  
    14.                         </StackPanel>  
    15.                     </DataTemplate>  
    16.                 </ItemsControl.ItemTemplate>  
    17.             </ItemsControl>  
    18.         </StackPanel>  
    19.     </Grid>  
    20. </UserControl>  

  • Now, in View First in Code-behind, you need to set data context in code behind file, as shown in below code.

    1. public partial class EmployeeView: UserControl {  
    2.     public EmployeeView() {  
    3.         InitializeComponent();  
    4.         // this.DataContext = new EmplyeeViewModel();  
    5.     }  
    6. }