Entry No. 15

Binding in ReactiveUI.

If you are working on XAML in C#, you must know the MVVM pattern. To achieve this, to make the View “react” to the changes in ViewModel, one of the best ways is using ReactiveUI.

This entry is about some reactive ways to bind your data.

One Way Bind

Sets up a one-way binding from a property on the ViewModel to the View.

this.OneWayBind(ViewModel, viewModel => viewModel.Name, view => view.Name.Text);

// or likes this
this.WhenAnyValue(x => x.ViewModel.Name).BindTo(this, view => view.Name.Text);

Two Ways Bind

Sets up a two-way binding between a property on the ViewModel to the View.

this.Bind(ViewModel, viewModel => viewModel.Name, view => view.Name.Text);

// We can choose when to update
this.Bind(ViewModel, viewModel => viewModel.SomeProperty,
    view => view.SomeTextBox,
    SomeTextBox.Events().LostKeyboardFocus);

Command Binding

Bind an ICommand to a control, or to a specific event on that control (how this is implemented depends on the UI framework):

// Bind the OK command to the button.
this.BindCommand(ViewModel, viewModel => viewModel.OkCommand, view => view.OkButton);

// Bind the OK command to when the user presses a key
this.BindCommand(ViewModel, viewModel => viewModel.OkCommand, view => view.RootView, "KeyUp");

// Invoke a command whenever the Escape key is pressed
this.Events().KeyUpObs
    .Where(x => x.EventArgs.Key == Key.Escape)
    .InvokeCommand(this, x => x.ViewModel.Cancel);

// Subscribe to Cancel, and close the Window when it happens
this.WhenAnyObservable(x => x.ViewModel.Cancel).Subscribe(_ => this.Close());
// or the short way
ViewModel.Cancel.Subscribe(_ => this.Close());

Data Type Conversion

We can use expression to convert one data type to another.

// Age is an integer, Text is a string
// In the last parameter, we .ToString() the integer
this.OneWayBind(ViewModel, viewModel => viewModel.Age, view => view.Name.Text, value => value.ToString());

Power of BindTo

With normal binding, the source of updating are the changes of binding property. That means for every change, the binding properties will be updated.

But with BindTo, we can decide WHEN and HOW.

// we can literary bind anything to anything
// only need some expressions
this.WhenAnyValue(x => x.SomeList.TotalAmount)
    .Select(x => x > 50) // WHEN
    .Select(x => x.ToString("N2") // HOW
    .BindTo(this, x => x.ViewModel.DisplayAmount);

The interest thing about BindTo is it can make a binding between 2 view models:

ViewOne.WhenAnyValue(v1 => v1.ViewModel.Name)
    .BindTo(ViewTwo, v2 => v2.ViewModel.Name)