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.