Knockout Style Observables in XAML

Implementing field level change notification in WPF, and how a Lambda Expression can be used to specify a composite property that raises change notifications automatically whenever an associated property changes.

This week there was a short discussion on the WPF Disciples about Knockout observables and the implications of field level and owner level data bindings. The discussion can be found in the guts of this post.

I wanted to explore the topic further, and I decided to take a stab at implementing something analogous to Knockout Observables and Computed Observables in WPF.

In this article we look at implementing field level change notification in WPF, and how a Lambda Expression can be used to specify a composite property that raises change notifications automatically whenever an associated property changes.

To get started, let’s first take a look at a class that illustrates how composite binding are ordinarily done in a viewmodel designed for XAML (see Listing 1). It’s a simple viewmodel that contains three properties. Two properties have backing fields, while the third (FullName) is a composite property; combining the
FirstName and LastName properties. When either of the non-composite properties change, change notification has to occur for the composite as well as non-composite properties.

The downside of this approach is that as the complexity of the viewmodel increases and dependencies creep in, you end up having to raise
PropertyChanged events for multiple dependent properties. While this example may seem dead simple (it is), over time potential faults may creep in because of this kind of interdependence.

Taking the Knockout JS Approach

I’ve been using Knockout quite a bit lately and I like the flexibility and versatility that the binding expression interpreter offers. Knockout allows you to combine observable values in a way that allows you to forego the kind of artificial dependence seen earlier. For example, on a web page you can produce the same string as the
FullName property seen in the last example using something like the following:

<span data-bind="text: firstName() + ' ' + lastName()"></span>

You can also achieve the same result using computed values in your viewmodel if you so desire.

In this article I’ve set out to see whether I could come up with something that emulates Knockout's field level notifications in observables and computed observables. I’m quite happy with the result and I believe it has potential. Stay tuned, because at the end of this article you will see how to create a computed property in C# like the following, which raises change notifications automatically:

Bridging the HTML-XAML Ravine

In WPF, when using the INotifyPropertyChanged approach to data binding, change notification occurs at the owner object level. The owner is the source property in a data binding, which is ordinarily the DataContext of your control. If you’re using the MVVM pattern this is likely your viewmodel or a nested property. It is the owner object of the property that has the responsibility of raising a
PropertyChanged event whenever the property changes.

Conversely, field level notification is where the source of the notification is the field itself (or in XAML, a property). The main advantage of field level notification is that your viewmodel does not need to contain any plumbing code for change notification. Field level notification isn’t achievable in XAML without defining an event for each property in your viewmodel. (Thanks to Bill Kemph for reminding me of field level notifications using dedicated events). This approach is usually avoided because it adds an undue amount of plumbing code to your viewmodel. A wrapper layer is presented in this article, which takes care of raising property changed events for you.

Two classes exist in the downloadable code that emulate the behaviour of Knockout’s observable and computed observable types:
ObservableValue and ComputedValue. Both implement
INotifyPropertyChanged and automatically raise the PropertyChanged event when an associated value has changed.

The ObservableValue implementation is rudimentary. Things get more interesting when we look at the
ComputedValue implementation that allows you to specify a LINQ expression, which is parsed by the
ComputedValue object to locate objects that implement INotifyPropertyChanged. When any such object changes, the computed value is recalculated. This allows you to create arbitrary composite properties in your viewmodel that respond to change notifications of any other associated object.

Understanding the ObservableValue Class

An ObservableValue property is defined much like a property using the traditional approach to INPC. The difference is that an
ObservableValue instance wraps the value, as shown in the following excerpt:

When an instance of ComputedValue is created, the specified expression is parsed recursively. Nested
MemberExpressions that refer to objects implementing INotifyPropertyChanged are identified (see Listing 4).

When a member expression is discovered, its owner is resolved using the ComputedValue.GetValue method. The class subscribes to the
PropertyChanged event of the owner object. A PropertyChangedEventHandler is created and placed in a collection along with a
WeakReference to the owner object (see Listing 5). When a change notification is received, the
ComputedValue object raises its own PropertyChanged event.

Retrieving the property value from the Lambda expression is done via expression compilation (see Listing 6). However, the expression is not able to be compiled directly as it is just a fragment. A Lambda expression is constructed by converting the specified expression into a
UnaryExpression. When compiled, the resulting func is called and the result returned. In most cases the result is your viewmodel. Though, it does not have to be.

In .NET the target of an event may be ineligible for garbage collection while the event source remains alive. Therefore if we do not unsubscribe from owner objects’
PropertyChanged events, a memory leak may ensue. The ComputedValue class implements
IDisposable and when disposed the ComputedValue instance
unsubscribes from all change events.

The ComputedValueIDisposable implementation loops over the items in the handlers dictionary (see Listing 7). If
KeyValuePair.Value property holds a WeakReference to the owner of the property, where the owner has not been disposed, the
PropertyChanged event is unsubscribed using the handler stored as the
KeyValuePair.Key property.

The downloadable code contains a simple single window application that displays two
TextBox controls. Each TextBox is bound to a viewmodel property of type
ObservableValue. There is a TextBlock that is bound to a
ComputedValue property, which combines the result of the two ObservableValue properties (see Figure 1). When the text in either of the
TextBoxes is changed, the TextBlock containing the full name is updated.

Note how the LastName property is converted to upper case. This is performed despite the fact that the call is embedded within the Lambda expression of the
ComputedValue.

Figure 1. Sample App.

Just to prove no funny business is taking place in the Window XAML, Listing 8 shows how the text properties are bound to the Value property of the
ObservableValue properties and the ComputedValue property.

Knockout JS has some elegant features that leverage the versatility of JavaScript and help to bridge the gap between XAML and HTML. In this article we looked at implementing field level change notification in WPF, and how a Lambda Expression can be used to specify a composite property that raises change notifications automatically whenever an associated property changes.

License

Share

About the Author

Daniel Vaughan is a Microsoft MVP and co-founder of Outcoder, a Swiss software and consulting company dedicated to creating best-of-breed user experiences and leading-edge back-end solutions, using the Microsoft stack of technologies--in particular WPF, UWP, and the Xamarin tools.

Daniel is the author of Windows Phone 8 Unleashed and Windows Phone 7.5 Unleashed, both published by SAMS.

Daniel is the developer behind several acclaimed mobile apps including Surfy Browser for Android and Windows Phone. Daniel is the creator of a number of popular open-source projects, most notably the Calcium MVVM Toolkit.

Would you like Daniel to bring value to your organisation? Please contact

For years i use a somewhat different approach:DelegateWatchCommand – a DelegateCommand without CommandManager[^] computation and a list of objects/properties it depends on are separated. Computations are defined by an arbitrary method (or lambda). the list of the sources is defined by a lambda, that allows for special constructions to handle collections and tree-like structs. So the computing expression may be () => F(), i.e. it doesnt expose the properties it really depends on. And sources are defined by a list: x => x.P1.P2, x => x.P33, x => x.MyColl.CollectionWatch( y => y.A, y => y.B). Another important point for me -- handling collections. How to express "recompute the value whenever membership of collection _vm.MyCollection changes or properties A or B of any member change their values". This is a typical requirement. Collections must be observable, of course. Can it be implemented with Knockout?

I've taken a slightly different approach to you, where properties that require monitoring are inferred entirely by the Lambda expression that resolves the value. While your approach is more flexible, I've done it this way for the sake of simplicity and also because I prefer not to capture the fact of the dependency in two places: in a list and in the property getter. My goal was to emulate Knockout observables. The developer can always write code in the viewmodel to handle edge cases.

I didn't include collection change notifications in the expression analysis. I will though.