Essentials Of MVVM πŸ’»πŸ“±πŸ–₯️

MVVM (Model-View-ViewModel) is a software architecture pattern that is widely used in the development of UI-centric programs nowadays. MVVM is a must-have design pattern during the development of WPF, UWP, and Xamarin for taking advantage of user device capabilities and browser memory to improve application performance. MVVM was originally defined by Microsoft for use with Windows Presentation Foundation (WPF) and Silverlight, having been officially announced in 2005 by John Grossman in a blog post about WPF( Formally known as Avalon).
 

Why use MVVM?

 
In traditional WPF or Silverlight development - developers used to create a UI using window or user control or page. For all relevant codes like event handling, initialization, business logic, we write in the UI's code-behind. This strategy increased the size of the UI class and has a tight coupling between Application UI, data binding logic, and business operations. This tight coupling (heavy dependency) increases the overhead of UI. The Application UI has to do some more stuff including rendering the UI. This overhead was reducing UI rendering performance and application performance too. In this same situation, two developers cannot work simultaneously on the same UI. It's possible, but one developer's changes might break the other's code. Now we can feel that all these problems exist because there is a very tight coupling between the components of the application. The MVVM pattern focuses on the separation of those concerns or tight coupling. MVVM separates graphical user interface development from business logic or back-end logic (data model) development. For this separation of concerns, MVVM introduces three Components.
  1. Model (Business rule, data access, model classes)
  2. View (User interface, XAML)
  3. View-Model (Middle man between view and model)

The Model

 
The model refers to the domain object. They’re usually structs or simple classes. The model represents the actual data or information we are dealing with, within the application. The key thing to remember with the model is that it holds the only information, not behaviors or services that manipulate the information.  
  1. public class Book : BindableBase  
  2.   {  
  3.       private string _title;  
  4.       private string _author;  
  5.       private string _category;  
  6.       private string _language;  
  7.   
  8.       public string Title  
  9.       {  
  10.           get { return _title; }  
  11.           set  
  12.           {  
  13.               if (_title != value)  
  14.               {  
  15.                   _title = value;  
  16.                   OnPropertyChanged();  
  17.               }  
  18.           }  
  19.       }  
  20.       public string Author  
  21.       {  
  22.           get { return _author; }  
  23.           set  
  24.           {  
  25.               if (_author != value)  
  26.               {  
  27.                   _author = value;  
  28.                   OnPropertyChanged();  
  29.               }  
  30.           }  
  31.       }  
  32.       public string Category  
  33.       {  
  34.           get { return _category; }  
  35.           set  
  36.           {  
  37.               if (_category != value)  
  38.               {  
  39.                   _category = value;  
  40.                   OnPropertyChanged();  
  41.               }  
  42.           }  
  43.       }  
  44.       public string Language  
  45.       {  
  46.           get { return _language; }  
  47.           set  
  48.           {  
  49.               if (_language != value)  
  50.               {  
  51.                   _language = value;  
  52.                   OnPropertyChanged();  
  53.               }  
  54.           }  
  55.       }  
  56.   }  

The View

 
The view is simply referring to a user interface that responsible to display visual elements and controls on the screen. They’re typically subclasses of UIView. The view contains a collection of visible elements, and also receives user input. This collection includes user interfaces (UI), animations, and text.
  1. <Window    
  2.     x:Class="App19.MainWindow"    
  3.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    
  4.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    
  5.     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"    
  6.     xmlns:local="clr-namespace:App19"    
  7.     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"    
  8.     Title="MainWindow"    
  9.     Width="800"    
  10.     Height="450"    
  11.     mc:Ignorable="d">    
  12.     <Window.DataContext>    
  13.         <local:MainWindowViewModel />    
  14.     </Window.DataContext>    
  15.     <StackPanel>    
  16.         <TextBox Text="{Binding MyBook.Title, Mode=TwoWay}" />    
  17.         <TextBox Text="{Binding MyBook.Author, Mode=TwoWay}" />    
  18.         <TextBox Text="{Binding MyBook.Category, Mode=TwoWay}" />    
  19.         <TextBox Text="{Binding MyBook.Language, Mode=TwoWay}" />    
  20.         <Button Command="{Binding UpdateCommand}" Content="Update" />    
  21.     </StackPanel>    
  22. </Window>     

The ViewModel

 
We can find ViewModel between the View and Model layers. It provides data binding between View and model data as well as handling all UI actions and interactions by using the command. The ViewModel also exposes schemes, commands, and other points that help maintain the state of the view, manipulate the model as the result of actions on the view, and triggers events in the view itself.
  1. public class MainWindowViewModel : BindableBase  
  2.     {  
  3.         private Book _myBook;  
  4.         public DelegateCommand UpdateCommand { getset; }  
  5.         public MainWindowViewModel()  
  6.         {  
  7.             UpdateCommand = new DelegateCommand(OnUpdateCommandExecute);  
  8.             MyBook = new Book { Title = "My Book", Author = "Avnish Kumar", Category = "Programming", Language = "English" };  
  9.         }  
  10.         public Book MyBook  
  11.         {  
  12.             get { return _myBook; }  
  13.             set  
  14.             {  
  15.                 _myBook = value;  
  16.                 OnPropertyChanged();  
  17.             }  
  18.         }  
  19.         private void OnUpdateCommandExecute()  
  20.         {  
  21.             //Update the book details.  
  22.         }  
  23.     }  
Here, we can see the ViewModel inherit a class BindableBase. This BindableBase class is the implementation of one of the two essential interfaces of the MVVM pattern. these are as following:
  1. INotifyPropertyChanged Interface: Notifies clients that a property value has changed.
  2. ICommand Interface: Provide the commanding behavior for UI elements.
ICommand and INotifyPropertyChanged interface are the two important Piller of MVVM. We use DataBinding to synchronize data between the model and the view in any WPF, UWP, SilverLight, or Xamarin project. When the binding is going to initialize, the value of the model is sent to the view once. But for every subsequent change, the model must notify the binding to transfer the value again. We can achieve this easily by the implementation of the INotifyPropertyChanged interface on the model. 
 
The other most-used mechanism to bind actions to the view is the commands. To provide a command, you have to implement the ICommand interface. Commands provide the glue between View and ViewModel for interactivity and provide the commanding behavior for UI elements. ICommand exposes two methods, Execute, and CanExecute, and an event, CanExecuteChanged. Execute performs the actions that are associated with the command. CanExecute determines whether the command can execute the current command target. CanExecuteChanged is raised if the command manager that centralizes the commanding operations detects a change in the command source that might invalidate a command that has been raised but not yet executed by the command binding. 
 
INotifyPropertyChanged interface implementation
  1. public abstract class BindableBase : INotifyPropertyChanged  
  2.    {  
  3.   
  4.        public event PropertyChangedEventHandler PropertyChanged;  
  5.        protected void Set<T>(ref T storage, T value, [CallerMemberName]string propertyName = null)  
  6.        {  
  7.            if (Equals(storage, value))  
  8.            {  
  9.                return;  
  10.            }  
  11.   
  12.            storage = value;  
  13.            OnPropertyChanged(propertyName);  
  14.        }  
  15.        protected void OnPropertyChanged([CallerMemberName]string propertyName = null) => PropertyChanged?.Invoke(thisnew PropertyChangedEventArgs(propertyName));  
  16.    }  
ICommand interface implementation
  1. public class DelegateCommand : ICommand  
  2.    {  
  3.        private readonly Action _execute;  
  4.   
  5.        private readonly Func<bool> _canExecute;  
  6.   
  7.        public event EventHandler CanExecuteChanged;  
  8.   
  9.        public DelegateCommand(Action execute)  
  10.            : this(execute, null)  
  11.        {  
  12.        }  
  13.   
  14.        public DelegateCommand(Action execute, Func<bool> canExecute)  
  15.        {  
  16.            _execute = execute ?? throw new ArgumentNullException(nameof(execute));  
  17.            _canExecute = canExecute;  
  18.        }  
  19.   
  20.        public bool CanExecute(object parameter) => _canExecute == null || _canExecute();  
  21.   
  22.        public void Execute(object parameter) => _execute();  
  23.   
  24.        public void OnCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);  
  25.    }  
  26.   
  27.    public class DelegateCommand<T> : ICommand  
  28.    {  
  29.        private readonly Action<T> _execute;  
  30.   
  31.        private readonly Func<T, bool> _canExecute;  
  32.   
  33.        public event EventHandler CanExecuteChanged;  
  34.   
  35.        public DelegateCommand(Action<T> execute)  
  36.            : this(execute, null)  
  37.        {  
  38.        }  
  39.   
  40.        public DelegateCommand(Action<T> execute, Func<T, bool> canExecute)  
  41.        {  
  42.            _execute = execute ?? throw new ArgumentNullException(nameof(execute));  
  43.            _canExecute = canExecute;  
  44.        }  
  45.   
  46.        public bool CanExecute(object parameter) => _canExecute == null || _canExecute((T)parameter);  
  47.   
  48.        public void Execute(object parameter) => _execute((T)parameter);  
  49.   
  50.        public void OnCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);  
  51.    }  
OK, we're done! I hope you've learned why MVVM is so essential during WPF, UWP, SilverLight, or Xamarin project development. For a better understanding of this MVVM implementation, you can visit my git repository. you can find this MVVM implementation in this NuGet package.


Similar Articles