Overview
There is a vast array of tutorials over the internet about the MVVM pattern and sadly most of them do not break the pattern down to the bare essentials. I will not say that their approach to teaching the pattern is wrong or that mine is the end all and be all method. Everyone learns differently and sometimes the basic approach is the best. That being said, I will do my best to explain the MVVM pattern with the basic implementation in mind.
This tutorial is broken down into two sections. Section 1 is theory with explanations. Section 2 is a simple project with a breakdown on the important pieces of code to understand. Let's get started with Section 1.
Section 1
The MVVM pattern is an extension to the MVC pattern that is mainly used in Web development. Instead of Model View Controller, it features a Model View and ViewModel. So, if you are a beginner to the MVVM pattern, you are probably wondering why this pattern is so important. You would be right to wonder this and the reasoning is quite simple. Code separation. Code separation allows you to keep your UI and your back end code separate. This is especially useful in various situations.
A primary example is, you are working on backend code while another developer is working on the UI. If you don't use the MVVM pattern, any changes the UI developer makes could break your code. The MVVM pattern helps eliminate this problem.
Additionally, whenever you use the MVVM pattern, it is important to note that you are now doing a declarative programming style.
What each portion of the MVVM model means and does
The Model is a class that exposes the data you want to use. In addition, this class also implements the INotifyPropertyChanged Interface.
The View is either your page or usercontrol (whichever you decide to use). This class should not have any backend code to it, however, there is one exception to this rule, that is Setting the DataContext to the ViewModel.
The ViewModel is a class that does all of the heavy lifting. This is where you would call a database, create an observablecollection and any other backend code you would need to implement.
Why DataBinding is important with MVVM
Databinding enables the user to bind objects so that whenever the other object changes, the main object reflects its changes. The main motive is to ensure that the UI is always synchronized with the internal object structure automatically.
How to use DataBinding
In XAML, databinding is very simple to do. Consider the following snippet:
- <TextBox x:Name="textBox" Height="34" TextWrapping="Wrap" Text="{Binding Genre}" IsReadOnly="True"/>
Now, what if you want to write the code using C# instead of using XAML? Well, consider the following snippet:
- BindingSource binding = new BindingSource();
- binding.Add(new Models.ModelClass("Action");
- textbox.text = binding;
Section 2
First, let's talk about the model class.
In this example, we want to expose ReleaseDate, Name and Genre. We also want to implement the INotifyPropertyChanged Interface and call the event in the setter of each public property.
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Linq;
- using System.Runtime.CompilerServices;
- using System.Text;
- using System.Threading.Tasks;
- namespace PracticeProject.Models
- {
- public class ModelClass : INotifyPropertyChanged
- {
- private string name;
- public string Name
- {
- get { return name; }
- set
- {
- name = value;
- NotifyPropertyChanged();
- }
- }
- private string releaseDate;
- public string ReleaseDate
- {
- get { return releaseDate; }
- set
- {
- releaseDate = value;
- NotifyPropertyChanged();
- }
- }
- private string genre;
- public string Genre
- {
- get { return genre; }
- set
- {
- genre = value;
- NotifyPropertyChanged();
- }
- }
- public event PropertyChangedEventHandler PropertyChanged;
- private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
- {
- if (PropertyChanged != null)
- {
- PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
- }
- }
- }
- }
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.ComponentModel;
- using System.Linq;
- using System.Runtime.CompilerServices;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows.Input;
- using System.Xml.Linq;
- using System.IO;
- using System.Reflection;
- using System.Windows;
- namespace PracticeProject.ViewModels
- {
- public class ViewModelClass
- {
- public ObservableCollection<Models.ModelClass> Movies { get; set; }
- StreamReader _textStreamReader;
- public ViewModelClass()
- {
- LoadEmbeddedResource("PracticeProject.DataSources.Movies.xml");
- XDocument xdoc = XDocument.Load(_textStreamReader);
- var movies = xdoc.Descendants("Movies")
- .Select(x =>
- new Models.ModelClass
- {
- Name = (string)x.Element("Name"),
- Genre = (string)x.Element("Genre").Value,
- ReleaseDate = (string)x.Element("ReleaseDate").Value
- }
- ).ToList();
- Movies = new ObservableCollection<Models.ModelClass>(movies);
- }
- private void LoadEmbeddedResource(string resource)
- {
- try
- {
- Assembly _assembly;
- _assembly = Assembly.GetExecutingAssembly();
- _textStreamReader = new StreamReader(_assembly.GetManifestResourceStream(resource));
- }
- catch (Exception ex)
- {
- MessageBox.Show("Error Loading Embedded Resource: " + ex, "Error!", MessageBoxButton.OK, MessageBoxImage.Error);
- }
- }
- }
- }
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Data;
- using System.Windows.Documents;
- using System.Windows.Input;
- using System.Windows.Media;
- using System.Windows.Media.Imaging;
- using System.Windows.Navigation;
- using System.Windows.Shapes;
- namespace PracticeProject.Views
- {
- /// <summary>
- /// Interaction logic for MainView.xaml
- /// </summary>
- public partial class MainView : UserControl
- {
- public MainView()
- {
- InitializeComponent();
- DataContext = new ViewModels.ViewModelClass();
- }
- }
- }
Next, we create a stackPanel and will set the DataContext of it to be to the ListBox with the Path set as the selected item.
We do this to ensure that any item that is selected within the listbox will force the bound objects to update accordingly.
We will now create a label and TextBox within the stackpanel and bind the text of the TextBox to Genre and the context of the label to ReleaseDate.
- <UserControl x:Class="PracticeProject.Views.MainView"
- 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"
- xmlns:local="clr-namespace:PracticeProject.Views"
- mc:Ignorable="d"
- xmlns:vm="clr-namespace:PracticeProject.ViewModels"
- d:DesignHeight="300" d:DesignWidth="300">
- <Grid>
- <ListBox x:Name="listBox" ItemsSource="{Binding Movies, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="Name" Height="100" IsSynchronizedWithCurrentItem="True"/>
- <StackPanel Margin="10" VerticalAlignment="Bottom" DataContext="{Binding ElementName=listBox, Path=SelectedItem}">
- <Label x:Name="label" Content="{Binding ReleaseDate}" Height="36"/>
- <TextBox x:Name="textBox" Height="34" TextWrapping="Wrap" Text="{Binding Genre}" IsReadOnly="True"/>
- </StackPanel>
- </Grid>
- </UserControl>
Points of Interest
Once you get the hang of the basics of the MVVM pattern, you will be able to extend it further by learning the ICommand Interface.
Acknowledgements
It honestly took me several months to fully understand how the MVVM pattern works and I couldn't have done it without the help of people from StackOverflow, CodeProject, YouTube and the MSDN forums. So, in this section I would like to issue my sincerest thanks to all of the individuals responsible in helping me and others. There are too many people and sources to name, so if you are an individual that took time out to answer my questions, make tutorials such as mine, or even have made video tutorials, all of you have my sincerest thanks for helping other developers such as myself.
Christopher BoldenPosted Sep 22, 2015, 10:32 PM
This is a much needed tutorial. Excellent work.
Kiranteja JallepalliPosted Aug 1, 2015, 4:42 AM
very nice.Few people have guts to write articles on MVVM.
Santhakumar MunuswamyPosted Jul 31, 2015, 3:02 PM
Good work. Thanks for sharing
Santhakumar MunuswamyPosted Jul 31, 2015, 3:02 PM
Welcome
Santhakumar MunuswamyPosted Jul 31, 2015, 3:02 PM
Good Start
RakeshPosted Jul 31, 2015, 11:21 AM
Good work
Chervine BhiwooPosted Jul 31, 2015, 9:39 AM
Great Overview! Looking forward for more on MVVM!
Vignesh ManiPosted Jul 31, 2015, 8:54 AM
Nice
Rajeesh MenothPosted Jul 31, 2015, 8:16 AM
Nice one
Manas MohapatraPosted Jul 31, 2015, 6:40 AM
Nice Article..
Nilesh JadavPosted Jul 31, 2015, 6:26 AM
Nice one :)
Neeraj KumarPosted Jul 31, 2015, 4:00 AM
Good Article
Sibeesh VenuPosted Jul 31, 2015, 3:37 AM
Nice Share. Welcome
Gopi ChandPosted Jul 31, 2015, 3:18 AM
Great article to start with.......welcome to the community :)