Separation of Concerns (decoupling) or SoC is a principle that promotes best practices for software architecture. A ‘concern’ can be considered as an aspect of software functionality. For eg: The UI can be a concern, the business logic can be another concern and so on. The idea is to make sure each concern has a single, well-defined purpose and to find a balanced way to separate these features and concepts into different modules. This ultimately reduces duplicate code and keeps the modules decoupled from each other, making our application maintainable and manageable. As a very basic example of SoC, think about HTML, CSS and JavaScript, where all these technologies have a well-defined purpose. HTML defines the content structure, CSS defines content presentation and JavaScript defines how the content interacts and behaves with the user.
This article is published from the DotNetCurry .NET Magazine – A Free High Quality Digital Magazine for .NET professionals published once every two months. Subscribe to this eMagazine for Free and get access to hundreds of free .NET tutorials from experts
To realize the SoC principle, many Design Patterns have emerged over the years. For example, Model-View-Presenter (MVP) is suited for Windows Forms; Model-View-Controller (MVC) for ASP.NET MVC; Model-View-ViewModel (MVVM) works well with WPF and so on. For those interested, there’s a good article by Martin Fowler which explains the differences in these patterns over here.
What is Model-View-ViewModel (MVVM)?
XAML enables SoC in WPF, Silverlight, Windows Phone, and Windows 8 apps by separating the GUI of the application from the programming logic (coded in C #or VB.NET). Model-View-ViewModel (MVVM) is a design pattern that addresses SoC by allowing separation of your Business logic from the View (UI), which ultimately makes it easier to write unit tests and enables parallel development and design. It leverages the rich data binding capabilities of the XAML platform to expose the view model to the UI through the view's DataContext property. The business layer is also termed as Model whereas the ViewModel layer is responsible for exposing data objects from model to the UI using DataBinding. The ViewModel contains the View display logic where actions on UI can be handled using Commands properties declared in ViewModel.
Why MVVM Light?
In order to implement MVVM, you need to first understand commanding, messaging and binding. Then you need to understand the MVVM principles and implement these principles keeping a nice balance of power and simplicity in your development. You also need to provide Unit Testing support. All in all, this this takes a considerable amount of time and efforts. Luckily there are some nice MVVM frameworks to choose from like Prism, Cailburn, nRoute and Galasoft’s MVVM Light Toolkit. We will be exploring how to implement MVVM in WPF applications using the MVVM Light Toolkit by Laurent Bugnion.
The main purpose of the MVVM Light toolkit is to accelerate the creation and development of MVVM applications in WPF, Silverlight, Windows Store (RT) and for Windows Phone
The steps explained in this article are targeted specifically towards those who want to start with MVVM development and require a readymade toolkit for developing their WPF applications.
Installing MVVM Light
The MVVM Light toolkit can be downloaded from https://mvvmlight.codeplex.com/.
Project templates for Visual Studio 2012 and 2013 can be downloaded at http://mvvmlight.codeplex.com/releases/view/115541 . Currently the templates are only provided for Visual Studio 2012 and 2013 for the Pro, Premium and Ultimate editions. The MvvmLight.VS2012.vsix is for Visual Studio 2012 and MvvmLight.VS2013.vsix is for Visual Studio 2013. Depending on your versions of Visual Studio, once the respective template is installed, the project template will be available as shown in Figure 1:
Figure 1: MVVM Light Toolkit template in VS 2013
These project template by default provides the necessary libraries for the MVVM Light Framework with the project structure containing ViewModel classes, Models as shown in Figure 2:
Figure 2: MVVM Light libraries in Visual Studio
The libraries provide classes for implementing ViewModels with notifiable properties, Command, etc.
If we need to add MVVM Light libraries in an already existing project, then we can make use of the NuGet package to get these libraries. To do so, open an existing WPF project in Visual Studio > right-click on the project > select Manage NuGet Package > and select MVVM Light libraries from the NuGet Window as shown in Figure 3:
Figure 3: MVVM Light NuGet Package
Using MVVM Light in WPF 4.5
In the following steps, we will make use of MVVM Light for implementing a WPF application that performs some basic database operations. In these steps, we will make use of the following features of MVVM Light:
- Creating ViewModel using ViewModelBase class.
- Defining Notifiable properties in ViewModel class and raising PropertyChanged event on them using RaisedPropertyChanged method from the ViewModelBase class.
- Using RelayCommand class provided by Commanding for method execution based upon actions taken on UI.
- Using EventToCommand class provided by Commanding to defining commands on the WPF elements that do not by default support the Command property.
- Messenger feature for exchanging messages across objects.
For this application we will be using the following table in a sample SQL Server Company database:
Figure 4: SQL Server Employee table
Step 1: Open Visual Studio and create a WPF Application and name it ‘WPF_MVVMLight_CRUD’. To this project, add the MVVM Light Libraries using NuGet Package as discussed in Installation section. The project will add necessary libraries and the ‘ViewModel’ folder with the following two classes:
- MainViewModel.cs - This class is inherited from ViewModelBase class and it provides access to RaisedPropertyChanged method for notifiable properties.
- ViewModelLocator.cs - This class is used to contain static references for all the view models in the application. The constructor of this class provides a very simple IOC container for registering and resolving instances. The code is as shown here:
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
Information about the Service Locator can be found over here: http://msdn.microsoft.com/en-us/library/ff648968.aspx
The class registers the MainViewModel class in the IOC container in its constructor :
SimpleIoc.Default.Register();
It also provides an instance of the MainViewModel using read-only property as seen here:
SimpleIoc.Default.Register();
It also provides an instance of the MainViewModel using read-only property as seen here:
public MainViewModel Main
{
get
{
return ServiceLocator.Current.GetInstance();
}
}
The ViewModelLocator instance will be registered in the App.Xaml resources:
This will be used for DataBinding across views in the application.
Step 2: In the project, add a new folder with the name ‘Model’. In this folder, add a new ADO.NET Entity Data Model with the name ‘CompanyEDMX’ > select the SQL Server Database and the EmployeeInfo table. After the completion of the wizard, the following table mapping will be displayed:
Figure 5: Employee Table Mapping
Step 3: Now add a new folder called ‘Services’ and in this folder, add a class file with the following code:
using System.Collections.ObjectModel;
using WPF_MVVMLight_CRUD.Model;
namespace WPF_MVVMLight_CRUD.Services
{
///
/// The Interface defining methods for Create Employee and Read All Employees
///
public interface IDataAccessService
{
ObservableCollection GetEmployees();
int CreateEmployee(EmployeeInfo Emp);
}
///
/// Class implementing IDataAccessService interface and implementing
/// its methods by making call to the Entities using CompanyEntities object
///
public class DataAccessService : IDataAccessService
{
CompanyEntities context;
public DataAccessService()
{
context = new CompanyEntities();
}
public ObservableCollection GetEmployees()
{
ObservableCollection Employees = new ObservableCollection() ;
foreach (var item in context.EmployeeInfoes)
{
Employees.Add(item);
}
return Employees;
}
public int CreateEmployee(EmployeeInfo Emp)
{
context.EmployeeInfoes.Add(Emp);
context.SaveChanges();
return Emp.EmpNo;
}
}
}
This code defines an interface for accessing data from the database using Entity Framework.
Step 4: To register the Data Access service in the IoC, we need to register the DataAccessService class in it. To do so, open the ViewModelLocator class, and add the following line:
SimpleIoc.Default.Register();
The namespace for the DataAccessService class must be used in the ViewModelLocator class.
Step 5: Let’s implement the logic for reading all Employees from the table.
In the MainViewModel class, add the following Public notifiable property:
ObservableCollection _Employees;
public ObservableCollection Employees
{
get { return _Employees; }
set
{
_Employees = value;
RaisePropertyChanged("Employees");
}
}
This property will be exposed to the UI. The setter of the property calls the RaisedPropertyChanged method which will internally raise PropertyChanged event when the data from the collection changes.
Define the IDataAccessService object at the ViewModel class level as shown here:
IDataAccessService _serviceProxy;
In the ViewModel class, declare the following method to fetch Employees data:
///
/// Method to Read All Employees
///
void GetEmployees()
{
Employees.Clear();
foreach (var item in _serviceProxy.GetEmployees())
{
Employees.Add(item);
}
}
The above method calls GetEmployees() method from the DataAccessService class and puts all Employees in the Employees observable collection.
In the ViewModel class, now define RelayCommand object as below:
public RelayCommand ReadAllCommand { get; set; }
Use the constructor dependency for passing the IDataAccessService to the ViewModel’s constructor. The object of the DataAccessService will be available from the IOC which we have registered in Step 4. Also instantiate the Employees observable collection and ReadAllCommand object:
public MainViewModel(IDataAccessService servPxy)
{
_serviceProxy = servPxy;
Employees = new ObservableCollection();
ReadAllCommand = new RelayCommand(GetEmployees);
}
The ReadAllCommand is passed with the GetEmployees() method.
Step 6: In the project, add a new MVVM View provided by the MVVM Light toolkit as seen here:
Figure 6: MvvmView template
Name this view ‘EmployeeInfoView.xaml’.
Note: By default, the MVVM Light View adds the WPF Window, so for this application we will be replacing the Window by a UserControl. Once you change the root tag of the View from Window to UserControl, in the code behind of the view, change the base class from Window to UserControl.
Step 7: In this view, add a DataGrid, TextBlock and a Button as shown in Figure :
Figure 7: UI Design of our application
In the XAML part, set the DataContext property of the UserControl to the ‘Main’ property exposed by the ViewModelLocator class:
DataContext="{Binding Main, Source={StaticResource Locator}}"
The ‘Locator’ is declared in the App.Xaml resources. Main is the public property exposed by the ViewModelLocator class which returns an object of the MainViewModel class. The above expression means the MainViewModel is now bound with the UserControl. This means that all public declarations (Notifiable properties and Commands) can be bound with the XAML elements on the View.
Bind the ReadAllCommand command and the Employees collection properties of MainViewModel to the Button and DataGrid respectively :
Step 8: Open MainWindow.xaml and change its width to 1300. Set the width of the Grid element to 1290 and create two columns in it, each of width 640. In the zeroth (0) column, add the EmployeesInfo view.
To add the View in the MainWindow.xaml, the namespace of the View must be registered in the Window tag:
xmlns:Views="clr-namespace:WPF_MVVMLight_CRUD.Views"
Now add the View to the Grid:
Step 9: Run the project and a View gets displayed. Click on ‘List All Employees’ and the result is as shown in the Figure 8:
Figure 8: List all employees
Passing Parameters from View to the ViewModel
In the previous steps, we discussed how to create ViewModel, defining notifiable properties and the RelayCommand. In this section, we will discuss how to send data from View to the View Model and write in into our database table.
Step 1: In the MainViewModel, declare the following property:
EmployeeInfo _EmpInfo;
public EmployeeInfo EmpInfo
{
get { return _EmpInfo; }
set
{
_EmpInfo = value;
RaisePropertyChanged("EmpInfo");
}
}
The EmployeeInfo object will be used to add new Employee record.
Define the following method which accepts the EmployeeInfo object and saves it to the table by calling the CreateEmployee() method from the DataAccessService class.
void SaveEmployee(EmployeeInfo emp)
{
EmpInfo.EmpNo = _serviceProxy.CreateEmployee(emp);
if(EmpInfo.EmpNo!=0)
{
Employees.Add(EmpInfo);
RaisePropertyChanged("EmpInfo");
}
}
The CreateEmployee method returns the EmpNo. If this is not zero then the emp object will be added into the Employees observable collection.
Now define the RelayCommand object property in the ViewModel class:
public RelayCommand SaveCommand { get; set; }
The RelayCommand generic type property is declared where T represent the input parameter; in our case T is of the type EmployeeInfo.
Instantiate EmpInfo and RelayCommand in the ViewModel constructor:
EmpInfo = new EmployeeInfo();
SaveCommand = new RelayCommand(SaveEmployee);
The RelayCommand is passed with the SaveEmployee() method. This is possible because the SaveEmployee method accepts EmployeeInfo as its input parameter. This is the same object defined in the declaration of the generic RelayCommand property.
Step 2: Open App.Xaml and in resources, add styles for TextBlock and TextBoxes :
Since these styles are defined in App.Xam,l without any key they will be applied for all TextBlocks and TextBoxes in the application.
Step 3: In the Views folder of the project, add a new UserControl (you can use MVVM Light View also), and name it as ‘SaveEmployeeView.xaml’. In the View, add TextBlocks, TextBoxes and a Button. Set the DataContext of the UserControl to the Main property of the MainViewModel.
DataContext="{Binding Main, Source={StaticResource Locator}}"
For all the TextBoxes, bind their Text property to the EmpInfo property and bind the command property of Button to the SaveCommand exposed by the Main ViewModel. Along with it, bind the EmpInfo property to the CommandParameter property of the button. This is the actual parameter which will be passed from View to ViewModel. The XAML is as shown here:
The View now looks as shown in Figure 9:
Step 4: Add the UserControl we just created in MainWindow.xaml in the second column (column index 1):
Step 5: Run the Application, click on the ‘List All Employees’ to display all employees in the DataGrid.
Figure 10: List All Employees View
I have not added any validations to keep the scope of this article concise, but you should. Enter Employee Data (except EmpNo) and click on the ‘Save Employee’ button. The record gets added. Now scroll to the bottom of the DataGrid and you will find our newly added the record:
Figure 11: Newly added record
We have seen how to make use of the generic command to pass parameters from UI to ViewModel.
Defining Commanding on UI Elements not having the Command property
UI elements like Button, RadioButton, etc. expose the command property using which methods from the ViewModel can be executed. But what if we need to have a search textbox on the UI in which when the data is entered, matching data from the textbox is searched from a collection and displayed on the UI. In this case, we need to change the behaviour of the textbox to support commanding.
When we add the MVVM Light libraries in the project, the project also adds the System.Windows.Interactivity.dll assembly. This assembly allows us to define behaviours for the UI elements.
The MVVM Light library provides an EventToCommand class under the GalaSoft.MvvmLight.Command namespace. This class allows us to bind any event of any FrameworkElement to ICommand. In our case, we will use the EventToCommand to execute a method on the ViewModel class by defining command on the TextChanged event of the TextBox.
Step 1: Open the MainViewModel and add the following property, method and command in it:
public string EmpName
{
get { return _EmpName; }
set
{
_EmpName = value;
RaisePropertyChanged("EmpName");
}
}
The string property will be bound with the TextBox in the View. This property will be set when the text is entered in the TextBox.
void SearchEmployee()
{
Employees.Clear();
var Res = from e in _serviceProxy.GetEmployees()
where e.EmpName.StartsWith(EmpName)
select e;
foreach (var item in Res)
{
Employees.Add(item);
}
}
The method filters Employees from the collection based upon the EmpName. Now define the RelayCommand object in ViewModel:
public RelayCommand SearchCommand { get; set; }
Instantiate Command object in the constructor of the MainViewModel by passing the SearchEmployee method to it:
SearchCommand = new RelayCommand(SearchEmployee);
Step 2: Open EmployeeInfoView.xaml and add a TextBlock and TextBox to it. To register the Interactivity and EventToObject to XAML we need the following assemblies in the UserControl tag:
xmlns:i=http://schemas.microsoft.com/expression/2010/interactivity
xmlns:mvvm="http://www.galasoft.ch/mvvmlight"
Define the DataBinding, interactivity for commanding on the TextBox as follows:
In the XAML, the TextBox is bound with the EmpName property of the MainViewModel. The UpdateSourceTrigger property of the Binding class is set to the PropertyChanged event; this means that when the text is entered in the textbox, the EmpName property will be set with the text in the textbox. The event trigger is defined inside the textbox for the TextChanged event. This means when the TextChanged event is fired, the EventToCommand will execute the SearchCommand method defined in the MainViewModel.
Step 3: Run the application, click on the ‘List All Employees’ button and all employees will be displayed in the DataGrid:
Figure 12: List All Employees
Enter some text in the EmpName to search the TextBox. The DataGrid will be populated by all Employee records having EmpName starting with the text entered in the textbox:
Figure 13: Search DataGrid
So using EventToCommand, we can easily bind the command to the FrameworkElement.
Managing Messaging across two Views
Typically when there are multiple Teams involved in the development stage, then there is a possibility that they design separate views and these views are present on the same container. For e.g. take the EmployeeInfoView which shows list of all employees and SaveEmployeeView which performs Create, Update like operations. Now the requirement is that when an Employee is selected from the EmployeeInfoView, it should be displayed in the SaveEmployeeView for Updation purpose. There is a possibility that since both these views are having their own ViewModels, data will be send across these ViewModels.
Since both views are separate, how do we send the selected employee from one view to other? Traditionally this can be made possible using Event handling mechanism. When an Employee is selected, raise the event and pass the employee information to this event and then listen to this event in some other view. This approach requires that both views should directly communicate with each other by having access to each other’s objects. This is a scenario of tight-coupling. So now the question is how to implement the same in a loosely-coupled manner?
The answer is to use the MVVM Light Messenger. This messenger provides a loosely-bound way to send message (data) from one ViewModel to other.
Diagrammatically the Messenger can be explained as below:
Figure 14: MVVM Light Messenger
Messenger is a singleton object which lives throughout the application. The sender ViewModel simply calls the static ‘Send’ method. The receiver ViewModel needs to register with the messenger to receive the object. It provides a call back function which gets called when the new message received. Let’s see how this is done.
Step 1: In the project add a new folder and name it ‘MessageInfrastructure’. In this folder, add a new class file:
using WPF_MVVMLight_CRUD.Model;
namespace WPF_MVVMLight_CRUD.MessageInfrastructure
{
public class MessageCommunicator
{
public EmployeeInfo Emp { get; set; }
}
}
The above class defines Emp property of the type EmployeeInfo. This will be used as a message (data) passed from one view to other.
Step 2: In the MainViewModel add the following method:
void SendEmployeeInfo(EmployeeInfo emp)
{
if(emp!=null)
{
Messenger.Default.Send(new MessageCommunicator() {
Emp = emp
});
}
}
Note: Please add the ‘GalaSoft.MvvmLight.Messaging’ namespace in the MainViewModel.
The above method accepts an EmployeeInfo object and calls the Send() method of the Messenger, which is typed to the MessageCommunicator class. This means that the View which calls the above method, must pass the EmployeeInfo object.
In the ViewModel define the following RelayCommand object:
public RelayCommand SendEmployeeCommand { get; set; }
The RelayCommand is defined with the parameter of the type EmployeeInfo. This means that it will execute method having input parameter of the type EmployeeInfo.
In the constructor of the ViewModel, define an instance of the RelayCommand as shown here:
SendEmployeeCommand = new RelayCommand(SendEmployeeInfo);
Step 2: Open the EmployeeInfoView and define the EventToCommand for the DataGrid. Since the DataGrid is bound with the EmployeeInfo collection, when the DataGridRow is selected, it will select the EmployeeInfo object. We will map the SelectionChanged event of the DataGrid to the EventToCommand as shown here:
The above XAML shows that the Command property is bound with the SendEmployeeCommand declared in the ViewModel. The parameter sent from the UI to ViewModel is the SelectedItem, which is an EmployeeInfo object. Since the SendEmployeeCommand executes the SendEmployeeInfo method, the EmployeeInfo object will be passed to this method.
Step 3: Now we need to register for the messenger. To do so, in the MainViewModel add the following method:
void ReceiveEmployeeInfo()
{
if (EmpInfo != null)
{
Messenger.Default.Register(this,(emp)=>{
this.EmpInfo = emp.Emp;
});
}
}
The above method registers to the messenger and accepts the Emp message received. This message is then set to the EmpInfo notifiable property defined in the ViewModel class. Call this method in the constructor of the ViewModel. Since EmpInfo property is bound with the SaveEmployeeView, the Employee data will be displayed in it.
Step 4: Run the application, click on the Load All Employees button and the DataGrid will show all Employees. Select the Row from the DataGrid, the selected Employee Information will be displayed in the SaveEmployeeView as below:
This shows how easily we can establish Messenger base communication across two separate views.
Conclusion
MVVM has lot of advantages, but it can involve a lot of efforts to set things up on your own. The MVVM Light toolkit provides a lot of boiler plate code to implement MVVM based applications quickly and gives the user the freedom to customize and design the application. With the ViewModelBase from the MVVM Light toolkit, we no longer have to implement INotifyPropertyChanged. Additionally the MVVM light toolkit provides Visual Studio templates, a messenger, an IoC container and some useful code snippets that can make our WPF applications shine!
Download the entire source code from our GitHub Repository at bit.ly/dncm13-wpfmvvmlight
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Mahesh Sabnis is a DotNetCurry author and a Microsoft MVP having over two decades of experience in IT education and development. He is a Microsoft Certified Trainer (MCT) since 2005 and has conducted various Corporate Training programs for .NET Technologies (all versions), and Front-end technologies like Angular and React. Follow him on twitter @
maheshdotnet or connect with him on
LinkedIn