Automatic Component State Management in Blazor using INotifyPropertyChanged and INotifyCollectionChanged

In Blazor, changes to the state of a component become visible to the user when the component re-renders. Blazor has some conventions to make a component automatically re-render when it thinks there is a chance for the component’s state to be changed. According to Microsoft docs, Blazor considers the following situations as the sources of state-changes and will re-render the component accordingly:

  1. When the set of parameters of a component is updated by its parent component.
  2. When a cascading value is updated.
  3. When an event on the component is raised or an external EventCallback that the component is subscribed to is invoked.
  4. When StateHasChanged method of the component is explicitly called.

In simple scenarios, the first 3 conventions will be enough to keep your components reactive. But let your models and the relationship between your components get complicated, and you will most often than not find yourself explicitly calling StateHasChanged to make your components re-render.

A common source of a state-change is a modification to a variable that is used (through binding) to render the component in the most recent render cycle. A variable can be a member (field or property) of the component (possibly a parameter), a nested member of direct members of the component or an item of a collection member of the component. Some UI frameworks already have the mechanisms to detect such modifications and will automatically make the component re-render (e.g. the reactivity system of Vue.js does so by replacing data of a component with proxies that are able to notify the component when they are changed, bindings in WPF/Xamarin.Forms are able to track changes by subscribing to INotifyPropertyChanged and INotifyCollectionChanged instances present in the binding path). But Blazor does not react to such changes if the source of the change does not fall into one of the conventions explained above.

Consider the following sample component:

Name: @(Person.Name)
<ul>
@foreach (var skill in Person.Skills)
{
<li @key="skill">@(skill.Title)</li>
}
</ul>
<ChildComponent Person="@Person" />
@code {
[Parameter] public Person Person { get; set; }
}

Here if the child component changes Person.Name, adds a skill to Person.Skills, or changes the title of an existing skill, our component has no way to realize that it should re-render to reflect the changes, unless we modify the child component or our model class to make them notify our component when Person.Name is changed, Person.Skills collection is modified, or skill.Title is changed for all of the existing skills in Person.Skills and we modify our component to let Blazor know that the state has changed (by calling StateHasChanged) as the result of these notifications. Just imagine the amount of boilerplate code we need to write for every variable that the rendering of our component relies on!

Fortunately, the infrastructure to let an object notify its changes is already available in .NET. The key is to make Person and Skill classes implement INotifyPropertyChanged and raise PropertyChanged event when Person.Name and Skill.Title get changed and to use a collection that implements INotifyCollectionChanged (like ObservableCollection<T>) as the value of Person.Skills.

In Xaml-based frameworks you can use these two interfaces in your models and the framework will take care of handling the change events to update the UI. Unfortunately, Blazor is ignorant about these interfaces. Phork.Blazor.Reactivity is a library -which I’m the author of- that brings the support of these two interfaces to Blazor!

Using Phork.Blazor.Reactivity, we can apply the following simple changes to the above component to make it reactive! (Assuming our models are modified to implement INotifyPropertyChanged and use ObservableCollection<T> correctly and Phork.Blazor.Reactivity is installed and configured in our project)

@inherits ReactiveComponentBase
Name: @Observed(() => Person.Name)
<ul>
@foreach (var skill in ObservedCollection(() => Person.Skills))
{
<li @key="skill">@Observed(() => skill.Title)</li>
}
</ul>
<ChildComponent Person="@Person" />
@code {
[Parameter] public Person Person { get; set; }
}

With Phork.Blazor.Reactivity, you can take advantage of INotifyPropertyChanged and INotifyCollectionChanged to create reactive components. The library will take care of watching changes for you. It doesn’t end here, there are more features available in the library that you can learn about in its documentation.

Find out more:

🎯 Bonus Tip: If you plan to use MVVM in your Blazor application, using Phork.Blazor.Reactivty will give you the luxury of reusing your existing cross-platform view models from your WPF/Xamarin.Forms applications with less effort.

C# Expression Trees!

Have you ever wondered how a property of an object can be passed to a method? I mean the property itself, not its value! Why does it matter to be able to pass a property, you might ask. Let me explain with an example. Let’s say we want to write a method that accepts a string property of an object and prints the name of the property followed by its value. How should this method be written?

For the sake of demonstration, let’s suppose that we have a Person class that has two string properties, FirstName and LastName. personInstance is an instance of this class.

public Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
//... inside the main method
Person personInstance = new Person
{
FirstName = "John",
LastName = "Doe"
};

The goal here is to write a method PrintProperty in a way that if a property of an object is passed to it, it will print the name and the value of the property. For instance, if the method is called this way, PrintProperty(FirstName property of personInstance), it will print “FirstName: John”. Now the question is, how can we define this PrintProperty method? How can we pass the property to it?

First, let’s talk a bit about properties. In order for a property to be accessed at runtime, we need the property name and an object that has that property. Once we have this information, we can find the value of the property with help of reflection. So, the problem is now reduced to finding a way to pass an object and a property name to a method. In this post, I am going to explain three different approaches to address this problem.

Approach #1: The naive approach

We can simply pass the object and property name, and the rest can be handled by reflection.

static void PrintProperty1(object obj, string propertyName)
{
var property = obj.GetType().GetProperty(propertyName);
Console.WriteLine($"{propertyName}: {property.GetValue(obj)}");
}
// ... inside the main method
PrintProperty1(personInstance, "FirstName");

Here, we are using a string to identify the property. But what if at some point we decide to change the name of the property to Name instead of FirstName? Or what prevents me from passing “InvalidProperty” as the property name? There’s no way to ensure propertyName is a property of obj at compile-time.

Approach #2: Using nameof expression

Before C# 6.0, there was no good way to obtain the name of a property programmatically. But C# 6.0 introduced nameof expression that is helpful in this situation.

static void PrintProperty2(object obj, string propertyName)
{
var property = obj.GetType().GetProperty(propertyName);
Console.WriteLine($"{propertyName}: {property.GetValue(obj)}");
}
// ... inside the main method
PrintProperty2(personInstance, nameof(personInstance.FirstName));

As you can see, the body of PrintProperty2 is the same as PrintProperty1, what has changed, is how we pass the property name to it. Using nameof expression, if we change name of the property to Name at some point, it won’t compile. But since the parameter is string, I’m not forced to use nameof and still nothing prevents me from passing “InvalidProperty” as the property name. This approach is OK but doesn’t look cool to me. Since what we are trying to achieve, is to pass the FirstName property to the method, wouldn’t it be better if we could simply pass personInstance.FirstName? Well, the answer is we can, somehow! Expression trees are here to help! Before moving on to the third approach, let’s talk about expression trees a bit.

You can be a C#/.net developer for years and have never heard of expression trees. Before explaining expression trees, I am going to ask you a simple question to test your knowledge of expression trees. Let’s assume that we’re going to assign the following lambda expression to a variable named x. obj is an object of a class that has an int property named prop. What kinds of possible types can replace var keyword below?

var x = () => obj.prop;

If your answer to this question does not include Expression<Func<int>>, you are probably ignorant of expression trees!

Normally, when you assign an expression, a+b for instance, to a variable x, the expression is computed and its value is assigned to x. So, after it is assigned, x only knows the computed value and has no idea how the value is computed, therefore if you change the value of a, the value of x won’t change. It’s not the same for lambda expressions. If you assign a lambda expression, let’s say () => a + b, to a variable f, the value a+b is not computed at first. In contrast to the previous case, where the value got computed and stored in x, here, the instruction to produce the value is stored in f. Strictly speaking, f captures variables a and b and every time it gets invoked, it adds these two variables and returns the value. With the help of expression trees, you can create and manipulate these instructions.

Cool as it may sound, it seems hard to find a real-world situation in which expression trees can come in handy. You might be surprised by the fact that how expression trees are being used in LINQ to Sql. For instance, Where extension method that is applied to IEnumerable<T> and Where extension method that is used for IQueryable<T>, although look similar in usage and name, accept different type of parameters. Former expects a Func<T, bool> as the first parameter while the latter expects a Expression<Func<T, bool>>. You can learn more about this usage here.

Now, let’s see how expression trees can help us solve our main problem!

Approach #3: Expression Trees!

As I mentioned above, we can just pass personInstance.FirstName to the method. But if we do so, what the method will get is the value of personInstance.FirstName which is string “John”. So, we can instead pass () => personInstance.FirstName as an expression to the method and analyse it to find the object and its property member.

() => personInstance.FirstName as an Expression, is a LambdaExpression, it has a Body property that defines what the lambda expression will return. The Body property in this case is a MemberExpression - since we are trying to access a member of another expression using the dot operator. The member expression itself has an Expression property, which defines the expression that we are trying to access its member and a Member property. Member property of the MemberExpression is a MemberInfo object that has a Name property, which in this case is “FirstName”. There is an implicit level of member accessing here. Since personInstance is defined inside the main method, it cannot be accessed elsewhere, hence, the lambda expression will capture the personInstance object and store it inside a compiler-generated class as a field named personInstance. So personInstance object is a property inside an implicit compiler-generated class. As a result Expression property of the member expression, in this case, is also a MemberExpression with its Member property being a MemberInfo with personInstance name and its Expression being a ConstantExpression that has that compiler-generated class as its value. Following diagram demonstrates how the expression tree of this simple lambda expression will look like.

expression tree Expression tree of () => personInstance.FirstName (the diagram is made using draw.io)

Now we can use the above information to implement PrintProperty3 method.

static void PrintProperty3(Expression<Func<string>> propertyExpression)
{
var memberExpression = propertyExpression.Body as MemberExpression;
var implicitMemberExpression = memberExpression.Expression as MemberExpression;
var objectName = implicitMemberExpression.Member.Name;
var constantExpression = implicitMemberExpression.Expression as ConstantExpression;
var owner = constantExpression.Value;
var obj = owner.GetType().GetField(objectName).GetValue(owner);
var property = memberExpression.Member as PropertyInfo;
Console.WriteLine($"{property.Name}: {property.GetValue(obj)}");
}
// ... inside the main method
PrintProperty3(() => personInstance.FirstName);

In this approach, the method body is longer compared to the ones in previous approaches. However, when it comes to using it, passing the property is more straightforward. We can feel that we’re actually passing a property. In this case if we decide to rename FirstName property to Name we will get a compilation error. This approach is not completely safe though, we can pass () => “Hello” as the parameter! But at least we’re not relying on strings to specify properties. I personally prefer not to use nameof expression unless there is no better choice.

We just learned a new technique to specify properties. In the next part I’ll explain how this technique can be used in WPF/Xamarin.Forms applications. If you don’t know or care about WPF or Xamarin.Forms you can skip this part.

Applications in WPF/Xamarin.Forms

XAML-based technologies in C# like WPF or Xamarin.Forms, provide an ICommand interface to implement command design pattern. It is common among developers to use a single DelegateCommand -or RelayCommand– class to create new commands instead of creating a new class and implementing ICommand for each new command. Let’s assume that you have a sign up form. There is a “I Agree to the Terms” checkbox that is bound to a bool property named Agreed in your view model. There is also a button that must be disabled if the checkbox is not checked. You create your command inside your view model this way:

// define SubmitCommand property inside the view model
DelegateCommand SubmitCommand { get; set; }
// ... inside the constructor
this.SubmitCommand = new DelegateCommand(this.Submit(), () => this.Agreed);

Obviously, the submit button on your form must be bound to SubmitCommand property. This way, even if you check the checkbox, you’ll notice that the button won’t be enabled. That’s because the button won’t automatically check your CanExecute command to see if it’s changed. If your CanExecute function depends on some of the properties in your view model, you should fire CanExecute event of DelegateCommand manually every time one of these properties is changed. It’s fine to add this.SubmitCommand.RaiseCanExecuteChanged() to the getter of Agreed property. But suppose that you have many commands that depend on Agreed property and also your SubmitCommand depends on some other properties. You’ll end up with ugly getters, and it would become a headache to manage their relations. However, you can take advantage of INotifyPropertyChanged interface and use the technique explained above to tell your commands to observe the properties. You can implement a method in your DelegateCommand class to watch for property changes. And then you can simply initialize your SubmitCommand this way:

this.SubmitCommand = new DelegateCommand(this.Submit(), () => this.Agreed);
this.SubmitCommand.ObservesProperty(() => this.Agreed);

And you’re done.

As a bonus, Prism library has a nice implementation of DelegateCommand class with ObservesProperty method. You can check it out on their github.

Welcome!

Creating my first blog on Blogfa when I was 10, has been one of the geekiest things I’ve ever done in my life. Being able to finally have an address of my own on the web was like a dream come true for me. Since then, I have created a number of blogs, none of which have been successful. Despite my inner desire to write, I have never been a successful blogger, actually, I have never been a blogger at all! All I did was sporadically write some random blog posts and then lose all the interest and motivation!

This time it’s going to be different, I have a new set of motivations and reasons to blog! I have realized that to be a successful blogger, it takes desire, consistency, and planning.

I intend to share my experiences, opinions, and adventures here. You may find posts mostly about computers, programming, games, and puzzles.