Reactive Extensions And Exrin MVVM Framework In Xamarin.Forms

Reactive Extensions (Rx) are powerful extensions, that allow you to use LINQ to compose asynchronous and event based code. Simply put, that means you can configure code to act on events, very easily. ReactiveUI is an MVVM framework that uses Reactive Extensions. Looking at the source code, it does appear to me a grouping of helper functions working together with Rx. But I want the power of Exrin as well, hence, I have gone out to see how I can get Reactive Extensions, and Exrin, working nicely together, to get the best of both worlds. I can’t use ReactiveUI, but I can use Rx. If you haven’t dealt with Rx before, have a look at my Introduction to Reactive Extensions (Rx.NET).

Configuring

Exrin uses a VisualState class, to hold all the properties, bound to the View. If we create a BaseVisualState class first, that all others inherit from, we can add in some shared functionality. Here we create an Observable, based off the INotifyPropertyChanged event. A similar approach could be used with any other MVVM framework.

public class BaseVisualState : Exrin.Framework.VisualState
{
    public BaseVisualState() 
    { 
        PropertyObservable = Observable.FromEventPattern( 
                (EventHandler<PropertyChangedEventArgs> ev) => new PropertyChangedEventHandler(ev), 
                 ev => this.PropertyChanged += ev, 
                 ev => this.PropertyChanged -= ev); 
    }

     public IObservable<EventPattern<PropertyChangedEventArgs>> PropertyObservable { get; private set; }

 }

Then our MainVisualState can inherit this class, and you insert the properties as usual.

public class MainVisualState : BaseVisualState 
{
    public string TextEntry { get { return Get<string>(); } set { Set(value); } }
    public string Output { get { return Get<string>(); } set { Set(value); } } 
}

Using Rx on the VisualState

Now, you can use Rx, on the VisualState in your app, just as you normally would. You will need to filter out the property by name, as shown here, to interact with the property you desire. This example is just taking the input changes to an Entry control, and then outputting them to a Label.

public class MainViewModel : Exrin.Framework.ViewModel 
{ 
    private IDisposable subscription; 
    public MainViewModel() : base(new MainVisualState()) 
    { 
        var visualState = VisualState as MainVisualState; 
        subscription = visualState.PropertyObservable   
                                  .Where(x => x.EventArgs.PropertyName == nameof(visualState.TextEntry))   
                                  .Subscribe(x =>   
                                  {   
                                      var args = x.EventArgs as PropertyValueChangedEventArgs;   
                                      visualState.Output = args.NewValue.ToString();   
                                  }); 
    } 

    public override void Disposing() 
    { 
        base.Disposing();
        subscription?.Dispose();
    }
}

Use the NewValue, to see the new value of properties. You also have OldValue, if you need it. You can then call commands in your ViewModel. ReactiveUI include a method called InvokeCommand, but you can all the Command directly via MyCommand.Execute(myParameter);

WhenActivated

ReactiveUI has a method called WhenActivated, that allows you to run code, only when activated, to avoid using resources when unnecessary. You can replicate this in Exrin, by tapping into the ViewStatus. It uses the same principle as the VisualState, where it is best to create a BaseViewModel, you can continue to use for all your ViewModels, and add a PropertyObservable. You can deactivate or reactivate subscriptions as needed

public class BaseViewModel : Exrin.Framework.ViewModel 
{ 
    public BaseViewModel() 
    { 
        PropertyObservable = Observable.FromEventPattern( 
                    (EventHandler<PropertyChangedEventArgs> ev) => new PropertyChangedEventHandler(ev), 
                    ev => this.PropertyChanged += ev, 
                    ev => this.PropertyChanged -= ev); 
    }
 
    public IObservable<EventPattern<PropertyChangedEventArgs>> PropertyObservable { get; private set; }
}

public class MainViewModel : BaseViewModel 
{ 
    private IDisposable subscription; 
    public MainViewModel() 
    { 
        subscription = this.PropertyObservable 
                           .Where(x => x.EventArgs.PropertyName == nameof(this.ViewStatus)) 
                           .Subscribe(x => 
                           { 
                               switch (ViewStatus) 
                               { 
                                   case VisualStatus.Visible:
                                       break; 
                                   case VisualStatus.Hidden:
                                       break; 
                                   case VisualStatus.Disposed: 
                                       subscription?.Dispose(); // Dispose itself 
                                   break;
                               }
                            });
    }
}

Of course, you could just add or remove subscriptions on the OnAppearing, OnDisappearing, OnPopped, OnNavigated, OnNavigating and the constructor, to perform the same things, without Rx.

Summary

Rx and Exrin work very nicely together, and we can have the best of both worlds. The very powerful Reactive Extensions, and Exrin’s powerful navigation and operation features. Just by adding a small helper function to a base VisualState, allows you to use Rx on all bindable properties. As for using Rx elsewhere in your Xamarin.Forms application, that continues to be the same as usual, and it does not matter which MVVM framework you use.

I am not too familiar with ReactiveUI, hence if there is any further advantages in ReactiveUI that you want to see how Exrin would map, please let me know.


XAMARIN.FORMS MONTHLY NEWSLETTER

JOIN 1,100+ SUBSCRIBERS

  1. Don't miss out on updates
  2. The latest info from this site, Xamarin and the community
  3. Unsubscribe at any time*

* We use MailChimp, with double opt-in, and instant unsubscribe

Microsoft MVP | Xamarin MVP | Xamarin Certified Developer | Exrin MVVM Framework | Xamarin Forms Developer | Melbourne, Australia

Related Posts