MVVM Pattern Using WPF in Visual Studio 2012

This article describes the basic use and functionality of the Model-View-View-Model (MVVM) pattern in WPF.

MVVM: an architectural pattern used in software engineering that originated from Microsoft that is specialized in the Presentation Model design pattern. It is based on the Model-View-Controller pattern (MVC), and is targeted at modern UI development platforms (WPF and Silverlight) in which there is a UX developer who has different requirements than a more "traditional" developer. MVVM is a way of creating client applications that leverage core features of the WPF platform, allows for simple unit testing of application functionality, and helps developers and designers work together with less technical difficulties.

VIEW: A View is defined in XAML and should not have any logic in the code-behind. It binds to the view-model by only using data binding.

MODEL: A Model is responsible for exposing data in a way that is easily consumable by WPF. It must implement INotifyPropertyChanged and/or INotifyCollectionChanged as appropriate.

VIEWMODEL: A ViewModel is a model for a view in the application or we can say as an abstraction of the view. It exposes data relevant to the view and exposes the behaviors for the views, usually with Commands.

Getting Started:

  • Creating a WPF Project. Open Visual Studio 2012.
  • Go to "File" -> "New" -> "Project..."
  • Select Window in installed templates
  • Select WPF Application
  • Enter the Name and choose the location.
  • Click OK

img1.jpg
Image 1.

Now create three folders in the root application. The Name should be Model, View, and View Model and now add a new class in the Model folder. My class name is User and adds this namespace:

using System.ComponentModel;

User.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel; 
namespace MVVMInWPF.Model
{
   
public class User : INotifyPropertyChanged
    {
       
private int userId;
       
private string firstName;
       
private string lastName;
       
private string city;
       
private string state;
       
private string country; 
       
public int UserId
        {
           
get
            {
               
return userId;
            }
           
set
            {
                userId =
value;
                OnPropertyChanged(
"UserId");
            }
        }
       
public string FirstName
        {
           
get
            {
               
return firstName;
            }
           
set
            {
                firstName =
value;
                OnPropertyChanged(
"FirstName");
            }
        }
       
public string LastName
        {
           
get
            {
               
return lastName;
            }
           
set
            {
                lastName =
value;
                OnPropertyChanged(
"LastName");
            }
        }
       
public string City
        {
           
get
            {
               
return city;
            }
           
set
            {
                city =
value;
                OnPropertyChanged(
"City");
            }
        }
       
public string State
        {
           
get
            {
               
return state;
            }
           
set
            {
                state =
value;
                OnPropertyChanged(
"State");
            }
        }
       
public string Country
        {
           
get
            {
               
return country;
            }
           
set
            {
                country =
value;
                OnPropertyChanged(
"Country");
            }
        } 
        #region INotifyPropertyChanged Members
       
public event PropertyChangedEventHandler PropertyChanged;
       
private void OnPropertyChanged(string propertyName)
        {
           
if (PropertyChanged != null)
            {
                PropertyChanged(
this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion
    }            
}

Now add a new class in ViewModel .

UserViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.ComponentModel;
using MVVMInWPF.Model;
 
namespace MVVMInWPF.ViewModel
{
   
class UserViewModel
    {
       
private IList<User> _UsersList;
       
public UserViewModel()
        {
            _UsersList =
new List<User>
            {
               
new User{UserId = 1,FirstName="Raj",LastName="Beniwal",City="Delhi",State="DEL",Country="INDIA"},
               
new User{UserId=2,FirstName="Mark",LastName="henry",City="New York", State="NY", Country="USA"},
               
new User{UserId=3,FirstName="Mahesh",LastName="Chand",City="Philadelphia", State="PHL", Country="USA"},
               
new User{UserId=4,FirstName="Vikash",LastName="Nanda",City="Noida", State="UP", Country="INDIA"},
               
new User{UserId=5,FirstName="Harsh",LastName="Kumar",City="Ghaziabad", State="UP", Country="INDIA"},
               
new User{UserId=6,FirstName="Reetesh",LastName="Tomar",City="Mumbai", State="MP", Country="INDIA"},
               
new User{UserId=7,FirstName="Deven",LastName="Verma",City="Palwal", State="HP", Country="INDIA"},
               
new User{UserId=8,FirstName="Ravi",LastName="Taneja",City="Delhi", State="DEL", Country="INDIA"}           
            };
        }
       
public IList<User> Users
        {
           
get { return _UsersList; }
           
set { _UsersList = 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
        }
    }
}

Now add a new view in the View folder.

MainPage.xaml

<Window x:Class="MVVMInWPF.View.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainPage" Height="485" Width="525">
    <Grid Margin="0,0,0,20">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <ListView Name="UserGrid" Grid.Row="1" Margin="4,178,12,13"  ItemsSource="{Binding Users}"  >
            <ListView.View>
                <GridView x:Name="grdTest">
                    <GridViewColumn Header="UserId" DisplayMemberBinding="{Binding UserId}"  Width="50"/>
                    <GridViewColumn Header="First Name" DisplayMemberBinding="{Binding FirstName}"  Width="80" />
                    <GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding LastName}" Width="100" />
                    <GridViewColumn Header="City" DisplayMemberBinding="{Binding City}" Width="80" />
                    <GridViewColumn Header="State" DisplayMemberBinding="{Binding State}" Width="80" />
                    <GridViewColumn Header="Country" DisplayMemberBinding="{Binding Country}" Width="100" />
                </GridView>
            </ListView.View>
        </ListView>
        <TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,7,0,0" Name="txtUserId" VerticalAlignment="Top" Width="178" Text="{Binding ElementName=UserGrid,Path=SelectedItem.UserId}" />
        <TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,35,0,0" Name="txtFirstName" VerticalAlignment="Top" Width="178" Text="{Binding
ElementName=UserGrid,Path=SelectedItem.FirstName}" />
        <TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,62,0,0" Name="txtLastName" VerticalAlignment="Top" Width="178" Text="{Binding
ElementName=UserGrid,Path=SelectedItem.LastName}" />
        <Label Content="UserId" Grid.Row="1" HorizontalAlignment="Left" Margin="12,12,0,274" Name="label1" />
        <Label Content="Last Name" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="12,60,0,0" Name="label2" VerticalAlignment="Top" />
        <Label Content="First 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}"  />
        <TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,143,0,0" x:Name="txtCity" VerticalAlignment="Top" Width="178" Text="{Binding SelectedItem.City, ElementName=UserGrid}" />
        <Label Content="Country" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="12,141,0,0" x:Name="label2_Copy" VerticalAlignment="Top" />
        <TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,88,0,0" x:Name="txtCountry" VerticalAlignment="Top" Width="178" Text="{Binding SelectedItem.Country, ElementName=UserGrid}" />
        <Label Content="City" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="12,86,0,0" x:Name="label2_Copy1" VerticalAlignment="Top" />
        <TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,115,0,0" x:Name="txtSTate" VerticalAlignment="Top" Width="178" Text="{Binding SelectedItem.State, ElementName=UserGrid}" />
        <Label Content="State" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="12,113,0,0" x:Name="label2_Copy2" VerticalAlignment="Top" />
    </Grid>
</
Window>

Now let's run the application to see the output.

img2.jpg
Image 2.

Now select any row in the grid and click the "Update" button.

img3.jpg
Image 3.

img4.jpg
Image 4.

For more information, download the attached sample.