Reactive Extensions, ReactiveUI, and Whistling Tea Kettles

How does reactive programming work? “It’s all streams,” our program manager explained. “When you update a property in one part of the system, it causes another property in a different part of the system to update, too. It will take a bit to wrap your mind around.”

In my head, I pictured properties all over the system “magically” updating when a user clicks a button. Due to the lack of magic in programming, this mental image was not a complete picture—but it’s not that different from how reactive programming actually works.

Reactive Programming and Whistling Tea Kettles

Reactive programming is about streams–streams that you can create, merge, filter, mutate, and listen to. These streams are asynchronous and require no callbacks.

The object listening to the stream is the observer, and the stream is the observable. An observable can emit a value, a completed signal, or an error. The observer that is “listening” for these values is said to be subscribed to the observable.

In interactive programming, the application polls for data. By contrast, in reactive programming, the application is notified whenever there is new data. Thus, instead of the application determining the pace to query for data, data updates are simply passed on to the observing application.

I find it helpful to think of reactive programming like a whistling tea kettle. When I use a non-whistling tea kettle, I have to get up from the couch every couple of minutes to check if the water is boiling and–worst-case scenario–if the water has boiled over.

If I use a whistling tea kettle instead, I can sit on the couch and wait for the tea kettle to whistle to notify me when the water is boiling. If I no longer hear the whistling noise, I know that there has been an “error” and the water has most likely boiled over.

In the above scenario, I (the subscriber) am passively sitting on the couch and only react when I hear a sound from the tea kettle (the source). I will continue to hear the whistling sound from the kettle until either my housemate gets annoyed and turns off the kettle (completed signal) or the kettle falls off the stove and I hear a thump (error signal). As the observer, once I receive a signal (a whistling sound/whistling ending sound/thump), it is up to me how I react (turn off the tea kettle/shut off the stove/put the tea kettle back on the stove).

Looking at RX: Reactive Extensions for .NET

Listening for a tea kettle instead of checking on it every few minutes might sound useful, but how does one use the concept of reactive programming in an application?

Reactive Extensions is an API for reactive programming. In our project, we used the ReactiveUI library based on RX, a Reactive Extensions library specifically for .NET. RX is implemented by two interfaces: IObserver and IObservable.

The observable is the source–it notifies all of the observers of updates. The implementation of IObservable pushes elements of type T to the subscribed observers. For example, if T were a double representing temperature, each time the temperature updates, the observable would yield the new double value for temperature. The observable also keeps a list of subscribed IObserver implementations, letting the observable send notifications and dispose of observers.

The observer receives items from the observable to which it is subscribed. In the temperature example, the observer receives a temperature of type double each time the temperature changes.

ReactiveUI, An Extension of Reactive Extensions

ReactiveUI combines the Model-ViewModel-View pattern with Reactive Extensions, allowing the logic of view properties to be kept in one place.

To better understand the functionality of ReactiveUI, I built a small project that stored the state of two teapots. The pictures and text in the application are determined by which teapot state the user selects.

The user interface looks like this:

and this:

This is how I built the application using ReactiveUI:

Checkboxes are Watched Properties (implementing RaiseAndSetIfChanged)

The teapot state is a watched property. This means that whenever the teapot state changes in the View Model (in this case, via a command linked to a checkbox), the change will be propagated to the UI. Since I made each teapot state property implement the RaiseAndSetIfChanged interface from ReactiveUI, subscriptions to the property will receive the most current teapot state.


TeapotState _teapotState;
public TeapotState TeapotCurrentState
{
get { return _teapotState; }
set { this.RaiseAndSetIfChanged(ref _teapotState, value); }
}

In contrast, if a property did not implement RaiseAndSetIfChanged, subscriptions would only get the current property value upon subscription and receive no updates afterwards.

The checked box in the UI is determined by the teapot state. I created the checkmark component in the XAML and made the “is checked” property of each checkmark bind to the view model teapot state property.

Commands in Response to Toggling the Checkboxes (ReactiveCommand)

I wanted the teapot state property to update whenever the user clicked a checkbox. For instance, if the user clicked on the “whistling” checkbox, I wanted the current teapot state to be updated to whistling.

According to the ReactiveUI docs, it is best to have the view, so the XAML and code behind decide how a user invokes a command (e.g. clicking on a button, toggling a checkbox). The view model determines what happens in the system (e.g. state changing, updating the value of a watched property) when the user invokes the command.

Following that pattern, I linked a command to each checkbox in the view’s code behind file. In the View Model, I then created a reactive command for each checkbox and put the execution logic for the command in the View Model constructor.

Here is the creation and initialization of the command for the “whistling” checkbox:


public ReactiveCommand<Unit, TeapotState> CheckWhistlingCommand { get; private set; }
CheckWhistlingCommand = ReactiveCommand.Create(() => TeapotCurrentState = TeapotState.Whistling);

Now each time a checkbox is clicked, the watched property holding the current teapot state is updated.

Observing Changes in Selected Checkbox (WhenAnyValue/Observable)

ReactiveUI’s WhenAnyValue gets the current value of a watched property (assuming the watched property implements the RaiseAndSetIfChanged interface).

WhenAnyValue returns an observable that yields a new value whenever the observed property changes. In my case, the observed property was the teapot state. Thus, whenever the user selects a new teapot state, the observable will yield a new value. Because I had two teapots and wanted to know the state for each one, I created an observable for each teapot.

I then combined the two observables into one stream (using CombineLatest) and subscribed to the stream. I used that subscription reflecting the combined state of the teapots to determine the text for the message property (also bound to the UI).

Summary

In summary, if the user selects a new state for a teapot, a command is invoked.

When executed, the command will update the teapot state property (i.e if the teapot is whistling/not whistling/boiling over). The teapot state property determines which checkmarks are checked in the UI.

Because the teapot state property is being observed, the observer gets the updated value.

The first teapot state observable is combined with the second teapot state observable into a combined observable. The message property is updated whenever new values are pushed into this combined observable. The message property is bound to the UI in the code behind so the text in the UI reflects changes in teapot state.

I hope you found this post helpful in setting up a WPF application using ReactiveUI. Feel free to check out the source code for my demo application teapot-application.