Tag Archives: reacive extensions

First refactoring of the WinForms UI example

The hello world UI example started here is at first sight not optimal to demonstrate the positive effects of UI and app logic separation, since the amount of boilerplate code required to write the viewmodel without using a specialized framework is larger than the savings in the UI logic code. However, the testability of the viewmodel is granted having created the separation. The example also does not contain an explicitly defined model, apart from the “current” DateTime.

Windows Forms have bindings that understand the INotifyPropertyChanged interface, which we can recycle in the first refactoring of the WinForms example.

The complete project can be viewed on GitHub. As you will notice, the viewmodel is shared between this version and the first WPF one.

Only in the Form1_Load event handler of the form is tackled here.

The old code:

Observable.Interval(TimeSpan.FromSeconds(1))
    .ObserveOn(this)
    .Subscribe(x => textBox1.Text = DateTime.Now.ToLongTimeString());

var textChanged = Observable.FromEventPattern
    <EventHandler, EventArgs>(
    handler => handler.Invoke,
    h => textBox3.TextChanged+= h,
    h => textBox3.TextChanged-= h);

textChanged
    .ObserveOn(this) // scheduled on the Form's scheduler
    .Subscribe(x => textBox2.Text =
        textBox3.Text
        .Split()
        .DefaultIfEmpty()
        .Where(s=>s.Trim().Length>0)
        .Count()
        .ToString());

and the new one:

ViewModels.MyViewModel VM = new ViewModels.MyViewModel();

textBox1.DataBindings.Add("Text", VM, "CurrentTime");
textBox2.DataBindings.Add("Text", VM, "WordCount");

var textChanged = Observable.FromEventPattern
    <EventHandler, EventArgs>(
    handler => handler.Invoke,
    h => textBox3.TextChanged += h,
    h => textBox3.TextChanged -= h);

textChanged
    .Throttle(TimeSpan.FromSeconds(0.3))
    .ObserveOn(this)
    .Subscribe(_ => VM.TextInput = textBox3.Text);
[1. for a more MVVM approach, see a newer article]

Still the TextChanged event is used for the update of the viewmodel. The relevant changes are highlighted and are similar to the first WPF version. As you can see, the code is extremely similar to the WPF version.

The updated version instantiates the viewmodel, creates the bindings and subscribes the update of the viewmodel’s text. As a slight responsiveness improvement over the first two versions, the observable TextChanged events are throttled to 0.3 seconds with the idea that the word count is of no interest to the user during typing.

When the application becomes more elaborate, it’s expected that the savings become substantial, especially when using a specialized MVVM framework, such as ReactiveUI. At this stage, there is still no lifetime control of the observable’s subscriptions.

The next step is to start using ReactiveUI for the viewmodel.

A Responsive Windows Forms UI using Reactive Extensions

For WPF programming there is a Reactive Extensions extension called ReactiveUI. I like the idea very much, but the last time I have looked at the online documentation, it was slightly out of sync with the current version, and the examples are slightly more elaborate than hello world. I’ll have to return to ReactiveUI at a later point in time.

As it seems, many people still use WinForms. A typical Forms application contains quite a number of event handlers. What Rx promises is a declarative design of your program (UI) logic. Without getting too concerned with lifetime management of this hello world example, here it is:

Responsive WinForms using Rx

The first TextBox gets updated asynchronously with the current time, the second TextBox shows the word count of the text entered in the third TextBox. All that is defined in a single Load event handler, private void Form1_Load(…). You can get the code here.

The initialization of the logic (in Form1_Load) is as follows:

Update textBox1 with the current time asynchronously every second

Observable.Interval(TimeSpan.FromSeconds(1))
          .ObserveOn(this) // scheduled on the Form's scheduler
          .Subscribe(_ => textBox1.Text = DateTime.Now.ToLongTimeString());

No threading code needed :).

Convert an event handler into an observable and set its registration

var textChanged = Observable.FromEventPattern<EventHandler, EventArgs>
 (
  handler => handler.Invoke,
  h => textBox3.TextChanged+= h,
  h => textBox3.TextChanged-= h
 );

Subscribe to the textChanged observable in order to update the word count

textChanged
    .ObserveOn(this) // scheduled on the Form's scheduler
    .Subscribe(x => textBox2.Text =
        textBox3.Text
        .Split()
        .DefaultIfEmpty()
        .Where(s=>s.Trim().Length>0)
        .Count()
        .ToString());

That’s it. No other explicit event handlers, just these observables with lambdas.

Continued here….

Update: Since the original post, a lot has changed. ReactiveUI has a shiny new docs site, a lot of API improvements, and improved exposure.

Asynchronously access an object’s property repeatedly in C#

A question on Stackoverflow got me thinking of a beautiful way of reporting a value of an object in C# repeatedly, something like polling a sensor. Typically, polling is pull-based, but having been reading Intro to Rx for the second time lately, and being convinced of its push-base structural and syntactic eunoia, I’ve created a solution based on Rx listed below.

using System;
using System.Reactive.Concurrency;
using System.Reactive.Linq;

namespace rxtest
{
    class FrequencyMeter
    {
        Random rand = new Random();
        public int Hz
        {
            get { return 60+rand.Next(3); }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var obs = Observable.Generate<FrequencyMeter, int>(
                new FrequencyMeter(), //state
                x => !Console.KeyAvailable, // while no key is pressed
                x => x, // no change in the state
                x => x.Hz, // how to get the value
                x => TimeSpan.FromMilliseconds(250), //how often
                Scheduler.Default)
                .DistinctUntilChanged() //show only when changed
                ;

            using (var _ = obs.Subscribe(x => Console.WriteLine(x)))
            {
                var ticks = Observable.Interval(TimeSpan.FromSeconds(0.5))
                           .Subscribe(x=>Console.WriteLine("tick")); //an example only
                Console.WriteLine("Interrupt with a keypress");
                Console.ReadKey();
            }
        }
    }
}

producing an output similar to that:

Interrupt with a keypress
62
60
62
tick
61
60
tick
62
61
tick
60
62
61
tick
62

Now, with Rx available in C++ that would be interesting what will be left of the eunoia.