Getting Started With MVVM In WPF

MVVM is the way to write more organized and reusable code and to reduce the complexity of the code. Let's understand it in detail.

Model

  1. It is used just to hold the data. It has objects, properties, and variables to store the data in memory.
  2. There is no business logic in Model.
  3. Model objects raise ‘Property change Notifications’ i.e. bindings in WPF.
View

View is basically what users see on the screen; i.e., User Interface. 
  1. Some parts of View structure can be static, such as - Controls, Layouts; and some parts can be dynamic, such as - animations or state changes etc., depending on the requirement.
  2. MVVM pattern follows that View should not have any logic in code behind. Code behind in MVVM is used just to define the constructor and initializers and only to define the logic in which we need to access any UI element or its reference. But, events handling or other data related logic should not be there in code behind.
ViewModel

In WPF simple pattern (without using MVVM), we have lots of logic written in one place i.e. XAML and code behind. We directly interact with the UI objects using code behind. But, it is not the same in the MVVM pattern.

  1. Connection between View and Model.
  2. Gets data from Model object and provides it to View so that it can be displayed on UI.
  3. Data changes and interaction are done via ViewModel only.
  4. Navigation logic for different Views are also defined in ViewModel.
Let's try by creating a sample application step by step.
  1. Create a simple WPF project. I named it as "MVVMBasics".
  2. Add three folders in the project. i.e. Views, Models, and ViewModels. 
  3. Add a class in Models folder. I named it "CustomerModel". Let's now define the properties and PropertyChangedEventHandler (as we have already discussed that Model should contain properties) and notify any changes in those properties defined in interface INotifyPropertyChanged.
Let's see how to define.
  1. namespace MVVMBasics.Model {  
  2.     public class CustomerModel {}  
  3.     public class Customer: INotifyPropertyChanged {  
  4.         private string customerFirstName;  
  5.         private string cutomerLastName;  
  6.         public string CustomerFirstName {  
  7.             get {  
  8.                 return customerFirstName;  
  9.             }  
  10.             set {  
  11.                 if (customerFirstName != value) {  
  12.                     customerFirstName = value;  
  13.                     RaisePropertyChanged("CustomerFirstName");  
  14.                     RaisePropertyChanged("FullName");  
  15.                 }  
  16.             }  
  17.         }  
  18.         public string CustomerLastName {  
  19.             get {  
  20.                 return cutomerLastName;  
  21.             }  
  22.             set {  
  23.                 if (cutomerLastName != value) {  
  24.                     cutomerLastName = value;  
  25.                     RaisePropertyChanged("CustomerLastName");  
  26.                     RaisePropertyChanged("FullName");  
  27.                 }  
  28.             }  
  29.         }  
  30.         public string FullName {  
  31.             get {  
  32.                 return customerFirstName + " " + cutomerLastName;  
  33.             }  
  34.         }  
  35.         public event PropertyChangedEventHandler PropertyChanged;  
  36.         private void RaisePropertyChanged(string property) {  
  37.             if (PropertyChanged != null) {  
  38.                 PropertyChanged(thisnew PropertyChangedEventArgs(property));  
  39.             }  
  40.         }  
  41.     }  
  42. }  
Add ViewModel for CustomerModel and add a list of customers using dummy data.
  1. namespace MVVMBasics.ViewModel {  
  2.     public class CustomerViewModel {  
  3.         public ObservableCollection < Customer > Customers {  
  4.             get;  
  5.             set;  
  6.         }  
  7.         public void GetCustomers() {  
  8.             ObservableCollection < Customer > customers = new ObservableCollection < Customer > ();  
  9.             customers.Add(new Customer {  
  10.                 CustomerFirstName = "Neha", CustomerLastName = "Jangra"  
  11.             });  
  12.             customers.Add(new Customer {  
  13.                 CustomerFirstName = "Test", CustomerLastName = "Test"  
  14.             });  
  15.             customers.Add(new Customer {  
  16.                 CustomerFirstName = "Test1", CustomerLastName = "Test1"  
  17.             });  
  18.             Customers = customers;  
  19.         }  
  20.     }  
  21. }  
Add a user control to Views folder and add some UI elements to this user control, as shown below.
  1. <UserControl x:Class="MVVMBasics.Views.CustomerView" 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" mc:Ignorable="d" d:DesignHeight="600" d:DesignWidth="600" xmlns:local="clr-namespace:MVVMBasics.Views">  
  2.     <Grid>  
  3.         <StackPanel HorizontalAlignment="Left">  
  4.             <ItemsControl ItemsSource="{Binding Path = Customers}">  
  5.                 <ItemsControl.ItemTemplate>  
  6.                     <DataTemplate>  
  7.                         <StackPanel Orientation="Horizontal">  
  8.                             <TextBox Text="{Binding Path =CustomerFirstName, Mode = TwoWay}" Width="100" Margin="3 5 3 5" />  
  9.                             <TextBox Text="{Binding Path = CustomerLastName, Mode = TwoWay}" Width="100" Margin="0 5 3 5" />  
  10.                             <TextBlock Text="{Binding Path = FullName, Mode = OneWay}" Margin="0 5 3 5" /> </StackPanel>  
  11.                     </DataTemplate>  
  12.                 </ItemsControl.ItemTemplate>  
  13.             </ItemsControl>  
  14.         </StackPanel>  
  15.     </Grid>  
  16. </UserControl>  
Please see, in the above code, we have declared the bindings and mode of binding as per the properties defined in Model. And as we have discussed earlier, there will be no code in code behind of user control except the constructor and initializer.

Let's add this user control to MainWindow to see the results.
  1. <Window x:Class="MVVMBasics.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:MVVMBasics" xmlns:views="clr-namespace:MVVMBasics.Views" mc:Ignorable="d" Title="MainWindow" Height="750" Width="725">  
  2.     <Grid>  
  3.         <Grid>  
  4.             <views:CustomerView x:Name="CustomerViewControl" Loaded="CustomerViewControl_Loaded" /> </Grid>  
  5.     </Grid>  
  6. </Window>  
In code behind of MainWindow -
  1. namespace MVVMBasics {  
  2.     /// <summary>  
  3.     /// Interaction logic for MainWindow.xaml  
  4.     /// </summary>  
  5.     public partial class MainWindow: Window {  
  6.         public MainWindow() {  
  7.             InitializeComponent();  
  8.         }  
  9.         private void CustomerViewControl_Loaded(object sender, RoutedEventArgs e) {  
  10.             CustomerViewModel customerViewModelObject = new CustomerViewModel();  
  11.             customerViewModelObject.GetCustomers();  
  12.             CustomerViewControl.DataContext = customerViewModelObject;  
  13.         }  
  14.     }  
  15. }  
Now, run and see the output.
 
As soon as we change the text in the text box, a change in property value notifies and raises the PropertyChangedEventHandler. That changes the value of properties accordingly. So, the values of dataContext gets changed. Code sample is attached. You can download and directly run it.