Using ReactiveUI to Integrate INotifyPropertyChanged & IObservable

ReactiveUI offers some great helper functionality for integrating Reactive Extensions into your WPF user interfaces.

One of these is the ReactiveObject base class, which when derived from, grants your classes access to the ‘RaiseAndSetIfChanged’ helper function.

This conveniently wires up your properties to INotifyPropertyChanged/IObservable, so in one step you have a class that can be bound directly to your xaml AND observed using Rx.

	class Person : ReactiveObject
	{
		string _Name;
		public string Name
		{
			get { return Name; }
			set { this.RaiseAndSetIfChanged(x => x.Name, value); }
		}
	}

By convention ReactiveUI expects the backing field to have the same name as the property, but with an underscore prepended. So if you want a different backing field name, you have to explicitly reference it in RaiseAndSetIfChanged:

	class Person : ReactiveObject
	{
		string _name;
		public string Name
		{
			get { return _name; }
			set { this.RaiseAndSetIfChanged(x => x.Name, x=> x._name, value); }
		}
	}

The obvious question is then, ‘how do we subscribe to changes on these properties?’. The secret is to use the ReactiveObject base class function ObservableForProperty.

In the example below, we are doing something a little more complex that simply watching one property. Instead we are observing two properties containing cash amounts, and automatically updating a total when either changes.

	class Dividend : ReactiveObject
	{
		decimal _AnnouncedAmt;
		public decimal AnnouncedAmt
		{
			get { return _announcedAmt; }
			set { this.RaiseAndSetIfChanged(x => x.AnnouncedAmt, value); }
		}

		decimal _ForecastAmt;
		public decimal ForecastAmt
		{
			get { return _forecastAmt; }
			set { this.RaiseAndSetIfChanged(x => x.ForecastAmt, value); }
		}

		decimal _TotalAmt;
		public decimal TotalAmt
		{
			get { return _totalAmt; }
			set { this.RaiseAndSetIfChanged(x => x.TotalAmt, value); }
		}

		public Dividend()
		{
			Observable
				.Merge(	this.ObservableForProperty(x => x.AnnouncedAmt),
						this.ObservableForProperty(x => x.ForecastAmt))
				.Subscribe(_ =>  TotalAmt = AnnouncedAmt + ForecastAmt);
		}
	}

You’ll notice that the lambda parameter in the subscribe is an ‘_’, this is a functional programming convention for naming parameters that are not used in the lambda function.

There are a couple of advantage with this approach:

  • Clean and simple property get/set methods. The alternative implentation would either have to update the total in the setters, or even more verbosely, and unlikely in practise, listen on the INotifyPropertyChanged interface.
  • External code can also bind to changes on these properties. We’ve implemented the Observer pattern with very little code or overhead

ReactiveObject makes a great base class to derive your MVVM view models from.

Leave a Reply