Saturday, May 19, 2012

Create View and ViewModel binding in MVVM pattern


In this article I will describe how to create a binding between view and view model in MVVM pattern in simple steps. Before proceeding I assume that the reader has the basic knowledge of MVVM pattern i.e the division of the three components Model, View , ViewModel.

The example I have used below consists of a MainWindow which displays the customer details and the customer details are shown from a separate view name CustomerDetailsView(this is a usercontrol referred from MainWindow)We can add multiple user controls in the MainWindow –but for the sake of easy understanding  I have added only CustomerDetailsView.

Hierarchy looks like this:-

1. Create a ViewModelBase class(abstract class) implementing the INotifyPropertyChanged interface , since all the viewmodel classes will be using the OnPropertychange method it is a good approach to have it in a common place. This can be done as shown below:-

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {           
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                var e = new PropertyChangedEventArgs(propertyName);
                handler(this, e);
            }
        }         

2. Remove the StartupUri="MainWindow.xaml" in the App.xaml file and add the following code in the App.xaml.cs file

protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            MainWindow mainWindowView = new MainWindow();
            var mainWindowViewModel = new MainWindowViewModel();
            mainWindowView.DataContext = mainWindowViewModel;
            mainWindowView.Show();
        }

This is to create a binding between MainWindow.xaml and MainWindowViewModel.cs file by setting the dataContext of the MainWindow.xaml to the corresponding viewmodel.

3.Create a Resource dictionary , here I call it as Template.xaml. Here we add all the view and viewmodel bindings by creating data template as shown below and it is necessary to declare the view(vw) and viewmodel(vm) namespaces in the template file as shown below:-

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         
xmlns:vw="clr-namespace:ViewAndViewModelBinding.View"
xmlns:vm="clr-namespace:ViewAndViewModelBinding.ViewModel"  >
    <DataTemplate DataType="{x:Type vm:CustomerDetailsViewModel}">
        <vw:CustomerDetailsView/>
    </DataTemplate>   
</ResourceDictionary>

In the above code ViewAndViewModelBinding refers to the project name and View refers to the folder name in which all xaml files are present and ViewModel refers to the folder name in which all viewmodel files are present.

4. Add the reference to this resource dictionary in the MainWindow.xaml file as shown below:-

<Window.Resources>
        <ResourceDictionary Source="Templates.xaml" />
    </Window.Resources>

5. Now in this example the MainWindowView consists of a usercontrol that displays the customer details. This is the Usercontrol defined as a seperate view file named CustomerDetailsView and its respective viewmodel file is CustomerDetailsViewModel.
Add the following code in the MainWindow.xaml:-

<Grid>
          <UserControl Content="{Binding CustomerDetailsViewModelProperty }" />          
  </Grid>

6. Create a public property CustomerDetailsViewModelProperty of type CustomerDetailsViewModel and use OnPropertyChanged method as shown below in the MainWindowViewModelFile.

        private CustomerDetailsViewModel customerDetailsViewModel; 
        public CustomerDetailsViewModel CustomerDetailsViewModelProperty
        {
            get { return customerDetailsViewModel; }
            set
            {
                customerDetailsViewModel = value;
                base.OnPropertyChanged("CustomerDetailsViewModelProperty");
            } 
        }

And instantiate it in the constructor as shown below

public MainWindowViewModel()
        {
            customerDetailsViewModel = new CustomerDetailsViewModel();
        }

In this way we have created the bindings between the view and viewmodel files.
I hope this will be helpful. Please share your comments and revert back if you have any querries.