MVVM Architecture

Introduction

 
Software architecture is very important. Without implementing software architecture, UI code can be tightly coupled with backend code. This increases the cost of maintenance and makes our code Spaghetti, as lines of code start increasing with time. To address this concern, there are many software architectures that are available, such as Model -View - Controller (MVC), Model-View-Presenter (MVP), Model-View-ViewModel (MVVM), Model-View-Update (MVU), etc. Each pattern has its own advantages. Design patterns evolve with time and we start using more modern patterns as per skills and team size. Mostly, enterprise applications are developed using architecture that makes code well maintained and easy to work.
 
In this tutorial, we are going to discuss MVVM Architecture. This software architecture pattern helps us to address the Separation of Concern. It separates the GUI design from the application's backend, making it loosely coupled. It is used mostly in developing client applications. Let's understand each component of MVVM.
 
Model
 
The model represents the domain model also considered as Business Logic / Data Access Logic or we can abstractly define it as the backend of the application. They hold application data.
 
View
 
View Represents the UI of the application. This is what the user interacts with. It is the presentation part.
 
ViewModel
 
It is the logic of View. The ViewModel is also called as presentation logic. The View and ViewModel communicate with each other. The Request from ViewModel is forwarded to Model / Business Logic Layer / Data Access Layer. It allows sharing of computed/resultant data to the view.
There are popular frameworks that provide MVVM Architecture, such as: 
  • DotVVM: Component-based MVVM Architecture for ASP.NET.
  • MVVM Light Toolkit: The popular toolkit to build client applications in XAML.
  • Knockout.js: Dynamic JavaScript UIs with the Model-View-View Model (MVVM) pattern.
  • Vue.js: A popular Javascript framework.
And much more...

Implementing Basic MVVM Architecture in WPF

 
We are going to implement MVVM architecture in WPF. The Building Blocks of MVVM architecture in WPF are below. Here is a bit of an overview of each.
  1. ICommand
    This interface provides the code contract for the commanding behaviour of Runtime XAML. It controls the behaviour such as enable, disable of control and behaviour on execution.
  1. INotifyPropertyChanged
    This interface defines the contract for behaviour when the value of a property changes. It raises PropertyChanged event when the value changes.
  1. Binding to Property
    It’s for data Binding, helps to easily present data in View. It has four components named,
    1. A binding target object.
    2. A target property.
    3. A binding source.
    4. A path to the value in the binding source to use.
It offers data flow in four ways:
  1. OneWay
  2. TwoWay
  3. OneWayToSource
  4. OneTime
Implementation Flow
 
 
Code Walkthrough

We will create a generic ICommand Implementation and name it RelayCommand. It will contain system defined delegates Func and Action. 
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4. using System.Windows.Input;  
  5.   
  6. namespace WpfAppMvvm.RelayCommands  
  7. {  
  8.     public class RelayCommand : ICommand  
  9.     {  
  10.         public event EventHandler CanExecuteChanged;  
  11.         private readonly Func<objectbool> canExecute;  
  12.         private readonly Action<object> execute;  
  13.   
  14.   
  15.         public RelayCommand(Func<objectbool> canExecute, Action<object> execute)  
  16.         {  
  17.             this.canExecute = canExecute;  
  18.             this.execute = execute;  
  19.         }  
  20.   
  21.         public bool CanExecute(object parameter)  
  22.         {  
  23.             return canExecute(parameter);  
  24.         }  
  25.   
  26.         public void Execute(object parameter)  
  27.         {  
  28.             execute(parameter);  
  29.         }  
  30.     }  
  31. }  
We will implement INotifyPropertyChanged in ViewModel, it will be implemented for every View that will be created. In this code, we will enable the submit button based on conditions. We will invoke OnProperyChanged() method on property set. This method contains an invocation of a PropertyChanged event.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel;  
  4. using System.Runtime.CompilerServices;  
  5. using System.Text;  
  6. using System.Windows;  
  7. using System.Windows.Input;  
  8. using WpfAppMvvm.RelayCommands;  
  9.   
  10. namespace WpfAppMvvm.ViewModels  
  11. {  
  12.     public class MainWindowViewModel : INotifyPropertyChanged  
  13.     {  
  14.         private string name;  
  15.   
  16.         public string Name  
  17.         {  
  18.             get { return name; }  
  19.             set {   
  20.                 name = value;  
  21.                 CheckAndEnableButton();  
  22.                 OnPropertyChanged();  
  23.             }  
  24.         }  
  25.   
  26.         private string phoneNumber;  
  27.   
  28.         public string PhoneNumber  
  29.         {  
  30.             get { return phoneNumber; }  
  31.             set {   
  32.                 phoneNumber = value;  
  33.                 CheckAndEnableButton();  
  34.                 OnPropertyChanged();  
  35.             }  
  36.         }  
  37.   
  38.   
  39.   
  40.   
  41.         public ICommand SubmitButtonCommand { getset; }  
  42.   
  43.         public event PropertyChangedEventHandler PropertyChanged;  
  44.   
  45.   
  46.         public MainWindowViewModel()  
  47.         {  
  48.             CheckAndEnableButton();  
  49.         }  
  50.   
  51.         // Create the OnPropertyChanged method to raise the event  
  52.         // The calling member's name will be used as the parameter.  
  53.         protected void OnPropertyChanged([CallerMemberName] string name = null)  
  54.         {  
  55.             PropertyChanged?.Invoke(thisnew PropertyChangedEventArgs(name));  
  56.         }  
  57.   
  58.   
  59.         public void CheckAndEnableButton()  
  60.         {  
  61.             bool isEnabled = false;  
  62.             string result = string.Empty;  
  63.             if (Name?.Length > 0 && PhoneNumber?.Length > 0) {  
  64.                 isEnabled = true;  
  65.                 result = string.Format("My Details are:\n{0}\n{1}\n", Name, PhoneNumber);  
  66.             }  
  67.             else  
  68.             {  
  69.                 isEnabled = false;  
  70.             }  
  71.             SubmitButtonCommand = new RelayCommand((ob) => { return isEnabled; }, (ob) => { MessageBox.Show(result); });  
  72.             OnPropertyChanged("SubmitButtonCommand");  
  73.         }  
  74.     }  
  75. }  
Bind the ViewModel with View through DataContext and name the Properties the same as defined in ViewModel.
  1. <Window x:Class="WpfAppMvvm.MainWindow"    
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    
  4.         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"    
  5.         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"    
  6.         xmlns:local="clr-namespace:WpfAppMvvm"    
  7.         xmlns:vm="clr-namespace:WpfAppMvvm.ViewModels"    
  8.         mc:Ignorable="d"    
  9.         Title="MainWindow" Height="450" Width="800">    
  10.     <Window.Resources>    
  11.         <Style TargetType="StackPanel">    
  12.             <Setter Property="Margin" Value="20"/>    
  13.         </Style>    
  14.         <Style TargetType="Button">    
  15.             <Setter Property="Margin" Value="10"/>    
  16.         </Style>    
  17.         <Style TargetType="TextBox">    
  18.             <Setter Property="Margin" Value="10,5"/>    
  19.         </Style>    
  20.         <Style TargetType="TextBlock">    
  21.             <Setter Property="Margin" Value="10,5"/>    
  22.             <Setter Property="TextAlignment" Value="Center"/>    
  23.         </Style>    
  24.     </Window.Resources>    
  25.     <Window.DataContext>    
  26.         <vm:MainWindowViewModel/>    
  27.     </Window.DataContext>    
  28.     <StackPanel>    
  29.         <TextBlock Text="Name"/>    
  30.         <TextBox Width="500" Text="{Binding Name}"/>    
  31.         <TextBlock Text="Phone Number"/>    
  32.         <TextBox Width="500" Text="{Binding PhoneNumber}"/>    
  33.         <Button Width="200" Command="{Binding SubmitButtonCommand}">Submit</Button>    
  34.     </StackPanel>    
  35. </Window>    

Summary

 
In this tutorial, we learned about the importance of architecture, MVVM architecture, and implementation of MVVM architecture in WPF.
 
Please feel free to share your thoughts, ideas and suggestions. Thanks for reading!!