WPF and MVVM
In this post we are going through the followings:
- What is MVVM and why it is used
- Create a WPF-MVVM – simple application
What is MVVM and why it is used
MVVM stands for: Model-View-ViewModel
Model − It simply holds the data and has nothing to do with any of the business logic.
ViewModel − It acts as the link/connection between the Model and View and makes stuff look pretty.
View − It simply holds the formatted data and essentially delegates everything to the Model.
MVVM is a software design pattern that is structured to separate program logic and user interface controls. MVVM is also known as model-view-binder and was created by Microsoft architects Ken Cooper and John Gossman.
Like many other design patterns, MVVM helps organize code and break programs into modules to make development, updating and reuse of code simpler and faster. The pattern is often used in Windows and web graphics presentation software.
The MVVM pattern is used in Windows Presentation Foundation (WPF), which runs on Microsoft’s .NET. Silverlight, a Microsoft WPF internet equivalent multimedia plug-in, also uses MVVM.
The separation of the code in MVVM is divided into View, ViewModel and Model:
- View is the collection of visible elements, which also receives user input. This includes user interfaces (UI), animations and text. The content of View is not interacted with directly to change what is presented.
- ViewModel is located between the View and Model layers. This is where the controls for interacting with View are housed, while binding is used to connect the UI elements in View to the controls in ViewModel.
- Model houses the logic for the program, which is retrieved by the ViewModel upon its own receipt of input from the user through View-
In the following figure you see relation between View, ModelView and Model.
Separated Presentation
To avoid the problems caused by putting application logic in code-behind or XAML, it’s best to use a technique known as separated presentation. We’re trying to avoid this, where we will have XAML and code-behind with the minimum required for working with user interface objects directly. User interface classes also contain code for complex interaction behaviors, application logic, and everything else as shown in the following figure on the left side.
Following image shows Seperated Presentation of UI and Model
- All in One: it adapts your application model for a particular user interface view.
- Separated Presentation: it’s where any nontrivial interaction logic lives, and by that, I mean code required to get your user interface to behave in the way you want.
With separated presentation, the user interface class is much simpler. It has the XAML of course, but the code behind does as little as is practical. The application logic belongs in a separate class, which is often referred to as the model.
Create a WPF-MVVM – simple application
In this part of this post, we will learn how to use MVVM patterns for simple input screen and the WPF application.
Let’s have a look at a simple example in which we will be using MVVM approach.
Step 1 − Create a new WPF app (.NET Framework 4.8) in C# project MVVMDemo.
Step 2 − Add the three folders (Model, ViewModel, and Views) into your project.
Step 3 − Add a StudentModel class in the Model folder and paste the below code in that class
using System.ComponentModel; namespace MVVMDemo.Model { public class StudentModel {} public class Student : INotifyPropertyChanged { private string firstName; private string lastName; public string FirstName { get { return firstName; } set { if (firstName != value) { firstName = value; RaisePropertyChanged("FirstName"); RaisePropertyChanged("FullName"); } } } public string LastName { get {return lastName; } set { if (lastName != value) { lastName = value; RaisePropertyChanged("LastName"); RaisePropertyChanged("FullName"); } } } public string FullName { get { return firstName + " " + lastName; } } public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(string property) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(property)); } } } }
Code explanation:
This class (as Model) simply holds the data and has nothing to do with any of the business logic.
INotifyPropertyChanged interface: is used to notify clients, typically binding clients, that a property value has changed. Studen object with a property called FirstName. To provide generic property-change notification, the Student type implements the INotifyPropertyChanged interface and raises a PropertyChanged event when FirstName is changed.
PropertyChangedEventHandler delegate: you identify the method that will handle the event. To associate the event with your event handler, add an instance of the delegate to the event. The event-handler method is called whenever the event occurs. PropertyChangedEventArgs provides the PropertyName property to get the name of the property that changed.
Step 4 − Add another calss and call it StudentViewModel into ViewModel folder and paste the following code.
using MVVMDemo.Model; using System.Collections.ObjectModel; namespace MVVMDemo.ViewModel { public class StudentViewModel { public ObservableCollection<Student> Students { get; set; } public void LoadStudents() { ObservableCollection<Student> students = new ObservableCollection<Student>(); u students.Add(new Student { FirstName = "Mark", LastName = "Allain" }); students.Add(new Student { FirstName = "Allen", LastName = "Brown" }); students.Add(new Student { FirstName = "Linda", LastName = "Hamerski" }); Students = students; } } }
Code explanation:
This class(View Model) builds a list of Student class and initialize the FirstName and LastName with a values. and It acts as the link/connection between the Model and View and makes Databinding from Model to View.
ObservableCollection<T>: WPF provides the ObservableCollection<T> class, which is a built-in implementation of a data collection that implements the INotifyCollectionChanged interface.
Step 5 − Add a new User Control (WPF) by right click Views folder and Select Add > User Control (WPF) and call it StudenView.StudentView.xaml
This shall create two files: StudentView.xaml and StudentView.xaml.cs as seen in the following figure:
Step 6 − Click Add button. Now you will see the XAML file. Add the following code into StudentView.xaml file which contains different UI elements.
<UserControl x:Class = "MVVMDemo.Views.StudentView"
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:MVVMDemo.Views"
mc:Ignorable = "d"
d:DesignHeight = "300" d:DesignWidth = "300">
<Grid>
<StackPanel HorizontalAlignment = "Left">
<ItemsControl ItemsSource = "{Binding Path = Students}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation = "Horizontal">
<TextBox Text = "{Binding Path = FirstName, Mode = TwoWay}"
Width = "100" Margin = "3 5 3 5"/>
<TextBox Text = "{Binding Path = LastName, Mode = TwoWay}"
Width = "100" Margin = "0 5 3 5"/>
<TextBlock Text = "{Binding Path = FullName, Mode = OneWay}"
Margin = "0 5 3 5"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
</UserControl>
Code explanation:
This class(acts a View) conreates a UserControl (ItemControl) and binds this to StudentView class (ViewModel) with two Textbox for FirstName and LastName and a TextBlock for FullName.
Step 7 − Add the StudentView into your MainPage.xaml file using the following code.
<Window x:Class = "MVVMDemo.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:MVVMDemo"
xmlns:views = "clr-namespace:MVVMDemo.Views"
mc:Ignorable = "d"
Title = "MainWindow" Height = "350" Width = "525">
<Grid>
<views:StudentView x:Name = "StudentViewControl" Loaded = "StudentViewControl_Loaded"/>
</Grid>
</Window>
Code explanation:
The above Code adds (hooks) the UserControl (StudenViwModel) to the MainWindow
Step 8 − Here is the implementation for Loaded event in the MainPage.xaml.cs file, which will update the View from the ViewModel.
using System.Windows;
namespace MVVMDemo {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void StudentViewControl_Loaded(object sender, RoutedEventArgs e) {
MVVMDemo.ViewModel.StudentViewModel studentViewModelObject =
new MVVMDemo.ViewModel.StudentViewModel();
studentViewModelObject.LoadStudents();
StudentViewControl.DataContext = studentViewModelObject;
}
}
}
Code explanation:
The above Code implement the event of "StudentViewControl_Loaded" when application is started or someting is changed in UserControl
Step 9 − When you compile and execute the code in project, you will receive the following output on your main window.
Step 10 − Change first name and last name from Mark Allain to May jonsson then the Full name is changed as seen in the following UI.
Because the binding for first name and last name is defined as Mode = TwoWay (look to the StudentView.xml file).
Search from View.xaml to ViewModel.vb or ViewModel.cs
In View.xaml find binding : path: text, set mouse over text and press “CTR+ ,” then a search field is opened and shows all the .vb files which is contains isWorking
e.g from kundView.xaml to kundViewModel.vb
In the kundView.xaml: select the isWorking as follow:
<Grid Grid.Column=”1″ Grid.Row=”1″ IsEnabled=”{Binding Path=isWorking,Converter={StaticResource NegateConverter}}”>
Select isWorkiong and then on the keyboard press to the CTR+, then you see a list of ViewModel.vb(.cs) you can select the file you want .
WPF – Debugging
Debugging in C#
In WPF applications, programmers deal with two languages such as C# and XAML. If you are familiar with debugging in any procedural language such as C# or C/C++ and you also know the usage of break points, then you can debug the C# part of your application easily.
Debugging in XAML
If you are expecting the same kind of debugging in XAML, then you will be surprised to know that it is not possible yet to debug the XAML code like debugging any other procedural language code. When you hear the term debugging in XAML code, it means try and find an error.
- In data binding, your data doesn’t show up on screen and you don’t know why
- Or an issue is related to complex layouts.
- Or an alignment issue or issues in margin color, overlays, etc. with some extensive templates like ListBox and combo box.
Debugging an XAML program is something you typically do to check if your bindings work; and if it is not working, then to check what’s wrong. Unfortunately setting breakpoints in XAML bindings isn’t possible except in Silverlight, but we can use the Output window to check for data binding errors
UI Debugging Tools for XAML
UI debugging tools were introduced for XAML with Visual Studio 2015 to inspect the XAML code at runtime. With the help of these tools, XAML code is presented in the form of a visual tree of your running WPF application and also the different UI element properties in the tree. To enable these tools, follow the steps given below (in visual studio 2022)
- Go to the Tools menu and select Options from the Tools menu.
- It will open the following dialog box.
- Go to the General Options under Debugging item on the left side.
- Tick the highlighted option, i.e., “Enable Just My XAML in Live Visual Tree” and click the OK button.
Now run any XAML application or use the XAML code MainWindow.xaml in this post.
When you execute the application, and press to the first icon from he left in the UI, it will show the Live Visual Tree where all the elements are shown in a tree as shown in the following figure:
XAML Binding Failures window in Visual Studio
When in WPF: View.xmal file something is wrong then you can find it in XAML Binding Failures window.
You can enable it via
You can open it, go to Debug > Windows > XAML Binding Failures.
Or, select the Binding failures button in the application toolbar. …
When there are no binding failures in the tool window, the icon shows as gray without a number next to it. …
A similar icon also appears in the Live Visual Tree tool window.
Another trick is via output window: Ctr+Alt+O then opens output window and then search error.
Conclusion
In this post, I have explained ,the Model, View, ViewModel (MVVM pattern). MVVM is a software design pattern that is structured to separate program logic and user interface controls. MVVM is also known as model-view-binder and was created by Microsoft.
I have also created a simple WPF project in .NET Framework and implement MVVM structure in this project. I have showed how you can debug in application and how to Enable UI Debugging Tool for XAML.
All Source code is in my Github
In my next post I am going to explore how to use ICommand Interface in WPF-MVVM MVVM – ICommand, RelayCommand and EventToCommand
This post is part of “WPF step by step”