Tuesday, June 28, 2016

Introduction to MVVM Pattern


Introduction:-  Purpose of this document is to provide a basic idea to the Model – View – ViewModel pattern. This document is prepared considering the beginners who are learning the pattern. Here I used simple wpf application code sample to explain the pattern.

Purpose:- The main purpose of MVVM pattern is to decouple the UI and code base, they can interact with the “DataBinding” concept. This concept provides more flexibility to change our user interface without any change in code base. Any change in data is communicated with the help of notifications.

The Pattern:-The core components of MVVM pattern are: Model, View and ViewModel. The following image will explain relationship between these three components.



            Let me explain the each component with simple code. Let us have an example of showing the employee data available in the xml file as shown below:-

<?xml version="1.0" encoding="utf-8" ?>
<Employees>
  <Employee>
    <Name>Leesa J</Name>
    <Phone>987654321</Phone>
    <Email>neils@company.com</Email>
    <Address>Neils Apt, 1st Block,3rd Cross, ABC street, XYZ State,Pin:123456 </Address>
  </Employee>
</Employees>

            For simplification purpose I have created one employee data, later you can introduce some more that according to your requirements. Let me explain the three components of MVVM.

1.The Model:- The model is the representation of data, in our case it is class that represents a employee. Let is create a model object called employee as shown below:-

public class Employee
    {
        private string myname;
        private int myPhoneNo;
        private string myEmail;
        private string myAddress;

        public Employee()
        {
            XmlDocument myDocument = new XmlDocument();
            myDocument.Load("EmployeeInfo.xml");
            myname = myDocument.SelectSingleNode(@"//Employees/Employee/Name" ).FirstChild.Value;
            myPhoneNo = Convert.ToInt32(myDocument.SelectSingleNode("//Employ      ees/Employee/Phone").FirstChild.Value);
            myEmail = myDocument.SelectSingleNode("//Employees/Employee/Email").FirstChild.Value;
            myAddress = myDocument.SelectSingleNode("//Employees/Employee/Address").FirstChild.Value;
        }

        public string Name
        {
            get { return myname; }
            set { myname = value; }
        }
         public int PhoneNo
        {
            get { return myPhoneNo; }
            set { myPhoneNo = value; }
        }
        public string Email
        {
            get { return myEmail; }
            set { myEmail = value; }
        }
        public string Address
        {
            get { return myAddress; }
            set { myAddress = value; }
        }
    }

As I said earlier this class is data representation, so for simplicity we read the xml file and populate the fields in the constructor itself.

2. ViewModel :- This is a bridge between our view and model. It  acts like a business logic. this exposes methods, commands and other points that help maintain the state of view, manipulates model as result of action. In our application we will have a simple class that holds the object of our model.

public class EmployeeViewModel
{
    private Employee myData; 
    public EmployeeViewModel()
    {
        myData = new Employee();
    }
    public Employee EmployeeData
    {
        get { return myData; }
        set { myData = value; }
    }
}

3. View :- This is actual data presenter. the view and view model communicate via data binding. ViewModel binding to view can be done by setting the DataContext of the view. Let us create a WPF form (View) that is bound to ViewModel as shown below

 <Window x:Class="SimpleMVVMExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="284" Width="525"
        xmlns:local="clr-namespace:SimpleMVVMExample">
    <Window.DataContext>
       <local:EmployeeViewModel x:Name="MyViewModel" />
    </Window.DataContext>
    <StackPanel Orientation="Vertical">
        <StackPanel Orientation="Horizontal">
            <Label Content="Name" />
            <TextBox HorizontalAlignment="Left" Height="23" Text="                              {Binding Path=EmployeeData.Name}" Width="120" />
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <Label Content="Phone" HorizontalAlignment="Left" />
            <TextBox Height="23" Text="                                                          {Binding Path=EmployeeData.PhoneNo}" Width="120" />
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <Label Content="Email" />
            <TextBox Text="{Binding Path=EmployeeData.Email}" 
                     VerticalAlignment="Top" Width="120" />
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <Label Content="Address" Width="46" />
            <TextBox TextWrapping="Wrap" Text="                                                    {Binding Path=EmployeeData.Address}" 
                      VerticalAlignment="Top" Width="120" />
        </StackPanel>
    </StackPanel>

Run the application you could see the data available in xml file appear on text boxes of form without having any code behind in your form. Now put a brake point in employee class’s Name property and change the Name text, you could see break point hits there this is the beauty of the MVVM J

Here we are populating the data in employee object while constructing the form object itself. Now let us suppose what happens if we update the data dynamically (Once form is created and loaded). Comment the code inside constructor of  EmployeeViewModel, run the application and check you could observe no data populated.

Notification:
            Now let us add a button in my form we will use click event to load the employee data (Note: Here we used click event of button for explanation, for complete decoupling we need to use command binding to button)

<StackPanel Orientation="Horizontal">
     <Button Content="LoadData" Margin="200,0,0,0" Click="Button_Click" />
</StackPanel>

Add a public method in EmployeeViewModel to load the data.

 public void LoadData()
 {
      EmployeeData = new Employee();
 }

Call this method in button click event.

private void Button_Click(object sender, RoutedEventArgs e)
{
    MyViewModel.LoadData();
}

Run the application and click on LoadData button. Still you will not able to see the data populated on the UI but if you put the breakpoint and check the execution everything looks perfect.

So what went wrong???

This is because your UI doesn’t know that there is change happened to the properties of ViewModel  which are bound to UI. UI will come to know about this only if we notify it by some events. To achieve this we use interface “INotifyPropertyChanged” which has an event called “PropertyChangedEventHandler” we need not do any changes in XAML if we use this interface (By default wpf ui listens to the event once you bind it to ViewModel). But we need to raise the event in ViewModel whenever we set the bounded property. The ViewModel code with notification is  as shown below.

public class EmployeeViewModel:INotifyPropertyChanged 
    {
        private Employee myData;

        public EmployeeViewModel()
        {
            //myData = new Employee();
        }

        public void LoadData()
        {
            EmployeeData = new Employee();
        }

        public Employee EmployeeData
        {
            get { return myData; }
            set
            {
                myData = value;
                if (null != PropertyChanged)
                {
                    PropertyChanged(thisnew PropertyChangedEventArgs("EmployeeData"));
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
 
While raising the propertychanged event we pass the name of the property that is been changed in PropertyChangedEventArgs object. so that ui will come to know which property is been changed.
Create Commands:
             As I already said that to achieve the complete decoupling of UI we use commands instead of events. Advantage of commands is that we can bind the same command for multiple items intead of creating events of each items (example: Cut , Copy and Paste can be achieved with button as well as context menus).
              Now in our previous example we used "Buuton_Click" event to load the employee data. Let us do it with the help of command. As first step we will create a class that inherits "ICommand" interface with name "LoadCommand" as shown below

public class LoadCommand:ICommand
    {
        public bool CanExecute(object parameter)
        {
            return true;
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            EmployeeViewModel model = parameter as EmployeeViewModel;
            model.LoadData();
        }
    }

This class implements two interface methods CanExecute and Execute with a parameter. here I have type casted the parameter object to "EmployeeViewModel" as I will be sending that object as parameter object in XAML. In order to bind the command to UI I need to have a property of the command in my view model. Let us create a property of the command in viewmodel and instantiate it in the view model constructor.

        private LoadCommand myCommand;
        public EmployeeViewModel()
        {
            myCommand = new LoadCommand();
        }



Now let us bind the command to our button as shown bellow

<StackPanel Orientation="Horizontal">
       <Button Content="LoadData" Margin="200,0,0,0" Command="{Binding            Path=CommandLoad}" CommandParameter="{Binding}"/>
</StackPanel>

Here you could see I have used binding as my "CommandParameter" this says that the object I have bounded i.e "EmployeeViewModel" Is used as the parameter.
Now remove the event code used in the forms code behind and run the application and check the output whether it is working as you expected. You are clear that on click of button Execute method is been called. Ok, then what is the use of CanExecute? Just return false instead of true and check the button is disabled there.This is the beauty of it without any much code we could enable and disable the button. We for simplicity i didn't used any logic here. You could use the logic as per your requirement by using the parameter object.