Introduction
The purpose of this blog post is to provide instructions on how to use the Microsoft MVVM Community Toolkit for complete beginners. I found it very confusing to learn how to use this library when I first learned the MVVM pattern (mostly due to a lack of simple instructions available online), so I hope to help others by offering this guide in a format that is easy as possible to understand.
Purpose
The MVVM Toolkit exists to reduce the amount of excessive boilerplate code that the MVVM design pattern requires. This post from Microsoft shows a good example of how all of the getter, setter, and event boilerplate code for a view model can be eliminated by using the Toolkit. Below are code snippets highlighting the most important comparisons.
Code required without using the MVVM Toolkit:
public class SampleViewModel : INotifyPropertyChanged
{
private string _name;
private int _value;
public event PropertyChangedEventHandler PropertyChanged;
public string Name
{
get => _name;
set => SetPropertyValue(ref _name, value);
}
public int Value
{
get => _value;
set => SetPropertyValue(ref _value, value);
}
protected void SetPropertyValue<T>(ref T storageField, T newValue, [CallerMemberName] string propertyName = "")
{
if (Equals(storageField, newValue))
return;
storageField = newValue;
RaisePropertyChanged(propertyName);
}
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Code required while using the MVVM Toolkit:
public partial class SampleViewModel : ObservableObject
{
[ObservableProperty]
private string _name;
[ObservableProperty]
private int _value;
}
In general, you can treat it as though every property that will be getting displayed and/or updated in the view model (and by extension, the view) should be assigned an ObservableProperty
attribute.
How to Use - View Model
The first step to using the MVVM Community Toolkit is to implement the ObservableObject
class to your view model class. To do this, mark the class as partial, then inherit the ObservableObject
class. For example, your view model class declaration should look like this:
public partial class SampleViewModel : ObservableObject
Now that you have implemented this class, you can start assigning the ObservableProperty
attribute to your view model properties.
For example, let's say you have a string property that you want to use to display the user's name in your view. Without using the MVVM pattern, you would declare it like so:
private string _name;
Or alternatively you would create it as a property with a public getter and a private setter like so:
public string Name { get; private set; }
When using the Community Toolkit, you instead need to assign the ObservableProperty
attribute and also must follow the naming convention of prepending an underscore then making the first letter of the property name lower case. The property must also have a private accessibility level assigned. This is because the toolkit library autogenerates public properties that you will see later below. Therefore, in this example the name property needs to be declared like so:
[ObservableProperty]
private string _name;
Now here is where some brand new coding conventions come into action. Now that you have declared the name as an observable property, the toolkit has automatically created a public property behind the scenes called Name
. This is the property you will be referencing any time you are using this property in your code. Under nearly no circumstances will you be using the _name
property in your code.
For example, let's say that when the user presses a button, you want to assign the string "Clicked" to the property so that this string is displayed in the view. The code logic inside your button-clicked method will look like this:
Name = "Clicked"
Even though you didn't create this public Name property yourself, this is how you interact with the property to update the view with the new string assignment.
How to Use - Model
You can apply the same principles described for the View Model to any of your Model code.
The toolkit also automatically creates optional methods for the property so you can trigger logic to execute when the property is changed. You usually would want to contain this type of logic within your Model class, but there is no reason why you cannot use the following logic in your view models.
For example, let's say you want to trigger an event every time that the Name property within one of your models is updated by the user. As long as you have the ObservableProperty
attribute applied, the toolkit will have methods created that you can utilize. Start by typing partial void On
inside your Model class using Visual Studio and Intellisense will show you all of the methods that were auto generated. In this case, I am going to demonstrate the OnNameChanged
method. This is what the method declaration will look like:
partial void OnNameChanged(string value)
{
// Code your logic here
}
As long as you have an event handler within the Model class, you can invoke events inside the OnNameChanged
method. This method will automatically be called every time the Name property is changed, such as if you have this property bound to a TextBox element where the user can type strings into. The toolkit takes care of all the work behind the scenes for you - you do not need to ever reference or directly call the OnNameChanged
method anywhere else in your code.
The complete example code of your model class could look similar to this:
public partial class ExampleModel : ObservableObject
{
[ObservableProperty]
private string _name;
public static event EventHandler<NameFieldChangedEventArgs>? NameFieldChanged;
partial void OnNameChanged(string value)
{
NameFieldChanged?.Invoke(this, new NameFieldChangedEventArgs { Value = value });
}
}
How to Use - View
Assuming that the view model is properly referenced, you can reference the public property in your view in order to display it. For example, to display the property in an AvaloniaUI TextBlock element in a XAML view, your TextBlock would be declared like so:
<TextBlock Text="{Binding Name}" />
Demonstration
If you wish to see all of these patterns in action, check out my AutoJobSearch project built with AvaloniaUI on GitHub.
What am I missing here? I have a WPF project in .NET FX 4.8, I have created a partial class that inherits from ObservableObject, I've decorated all the private fields with the ObservalbeProperty attribute, and then... nothing. Even if I build this by itself, with no other files present beside what the project template gives me, the class does not create the public properties, nor does it have the expected "partial void On____" methods available. I've installed CommunityToolkit.Mvvm version 8.2, and frankly I am stumped.