Bootstrap Series – Xamarin.Forms in ReactiveUI with Xamvvm

Welcome! This is the third entry in a series where I explore MVVM frameworks that can be used with Xamarin.Forms. As a by-product of my investigation, I’ll have a handy bootstrapped project of each framework to help you get started using the framework discussed!

tl;dr – source code

Over the course of the series, I’ll be examining the pros and cons of the following MVVM Frameworks:

  1. MVVM Light (source)
  2. Prism.Forms (source)
  3. ReactiveUI + Xamvvm (source) <– This post!

Call me biased, but I saved the best for my last(?) entry in this series about MVVM frameworks for Xamarin.Forms. ReactiveUI is a very powerful tool for building robust, fault resistant applications in a easy to understand, declarative manner. The learning curve is steep, but the dividends are definitely worth the effort – and I still consider myself an amateur! Not familiar with ReactiveUI? Take a look at this superb introductory video by Kent Boogaart, who also wrote a fabulous book on using ReactiveUI for any sort of development or check out the documentation to get started – I won’t have time to call out all the ReactiveUI goodies in this post, but I’ll highlight things that are important to our discussion 👨🏻‍🎓

So how, does Xamvvm come in to play? Since ReactiveUI enables us to employ the MVVM pattern already, its is technically unnecessary, but I like using Xamvvm in conjunction with ReactiveUI because it makes a lot of common tasks easier. Namely, it abstracts away any of the “routing” business that is the default behavior in ReactiveUI, which I find cumbersome compared to other MVVM frameworks, such as Prism. I’ll be sure to highlight what features are available via Xamvvm as we go along as well, which can be used on its own if ReactiveUI isn’t your cup of joe.

Getting Started

As usual, we’ll need to get some NuGet packages to begin development. For now, let’s focus on two important packages:

Install-Package Xamvvm.Forms.RxUI -Version 1.0.5

Take note that we are specifically asking for the ReactiveUI version of Xamvvm – As mentioned above, you could use Xamvvm.Forms on it’s own, and the navigation patterns and conventions vary slightly depending on which route you choose. For the purposes of this post, however, we assume all things will employ ReactiveUI.


Note: Installing the necessary NuGet Packages for Xamvvm directly from the package manager prior to version 1.0.5 seems to result in conflicting references for netstandard2.0 projects. As a workaround, you can manually add all the dependencies at the top level by modifying your csproj file by hand, rather than relying on auto-resolution. Take a look at this gist as a reference.

However, if you use the latest and greatest you shouldn’t run into any problems; Xamvvm author Daniel Luberda recently published an update fixing this issue.  Thanks Daniel!


Once we have all of the necessary dependencies sorted out, we can start diving in to MVVM. If you’ve followed along with my previous posts, the folder structure we want to set up should be familiar by now:

Screen Shot 2018-08-14 at 3.44.46 PM

For the sake of consistency, we will try to keep the structure and content as similar to the previous entry in this series as possible. As with the MvvmLight demonstration, let’s delete the default HomePage.xaml and create a new one within our Views folder, as well as a few other pages and a new Helpers folder, which contains some interesting classes we will discuss later.

Xamvvm Factory

Unlike with our Prism example, we don’t need to modify the base class of our App.xaml, so let’s turn our attention to setting up our App.xaml.cs to render our first page. Take a look:

Here, we set up our factory, which will resolve our Views based on the provided View Model. In order to make this association, we need to make sure each View knows about its backing ViewModel. This isn’t quite as clean as Prism, which can infer the relationship by convention (assuming View and ViewModel follow a specific naming pattern), but it does give us the advantage that we don’t need to register each ViewModel individually for navigation in a global registration method – we can simply create the association as we build out new pages directly in the code behind.

AppShell

As an example of this, let’s start by stetting up our AppShell view and backing ViewModel:

Here we can see the Xamvvm Factory at work: our MasterDetailPage inherits from IBasePageRxUI, to which we pass the type of ViewModel we want to resolve to. While I generally follow well-formed naming conventions for readability, there is no requirement to follow any explicit pattern – in fact, the ViewModel could be names something entirely different! To make Xamvvm happy, we need to implement two properties that describe the ViewModel and IViewFor for this page, which just need to have publicly available getters and setters each. We now turn to the ViewModel:

Notice that there isn’t anything interesting happening here, besides some housekeeping around the master/detail view and that we inherit from BasePageModelRxUI – this is key so that our View can properly resolve this ViewModel when called upon. From here on, we will start observing more ReactiveUI involvement and how it interacts with Xamvvm.

Commanding

From the perspective of the View, commanding in ReactiveUI is nearly identical to our previous examples in the series. In fact, beyond the initial establishment of data context, you can essentially copy/paste the previous example directly into this new project file, just as we did for Prism:

Things get slightly more interesting when we turn to the ViewModel, but still closely resembles our previous examples, just with a ReactiveUI twist

Reactive commands come in two flavors. Generally, we must supply a Parameter Type (input) and a Result Type (output), but for simple commands, we need not specify those values. Once declared, we can then instantiate each command via Task or from an function of type IObservable. I prefer the former, but the documentation goes into detail on other methods of initializing a command. For the sake of simplicity, we’ll stick to CreateFromTask for the remainder of this post.

Showing Alerts & Dialogs

Presenting dialogs and alerts elements can be a little tricky in ReactiveUI, so I typically stand up some simple helpers to save me a little trouble and stay D.R.Y . Let’s take a look at one for showing Action Sheets: We have a few supporting models to make this run, but the most important is our static implementations of the different type of user interactions we expect. For now, let’s assume we won’t need anything besides Errors, Alerts, and Action Sheets

Notice that we have three flavors of ReactiveUI’s Interaction construct, each taking an input parameter type and an output parameter type. Under normal circumstances, we’d need to register various user interaction handlers on a per page basis in the code behind for each view that might need them. However, we can instead create a static class that handles the common workloads for us, like so:

Ok! With all that in place now, we can finally wire up our command to present an action sheet.

Like in Prism, we can wait for the response on our user interaction and take appropriate action. This is definitely more work than relying on the IPageDialogService that was available to us in Prism.Forms, but ReactiveUI gives some other cool features we can exercise to make life easier. Take for example, error handling. Using ReactiveUI, we can compose all the things that might fail, and handle them similarly (if applicable – special cases should be split out accordingly)

In this contrived example, we purposely trigger an error, then handle it accordingly in our ReactiveUI subscriptions we establish in the Initialize method. There’s a lot more going on with Observables that I’m glossing over here, but that’s a topic for another post 🤔

Navigating

As mentioned earlier, I find navigating in vanilla ReactiveUI to be a bit cumbersome. Instead, by employing Xamvvm, things get much simpler. Take a look at the following example:

Notice how we PushPageAsNewInstance and then set some variables directly on the view model. With Xamvvm, when we push a page as a new instance, we are guaranteed to have a fresh instance of the ViewModel each time. We could also PushPageFromCache, in which the Xamvvm Factory will attempt to push a cached version – that is, one that is already constructed and (potentially) in a manipulated state – which can be useful when presenting data that changes infrequently (or not at all), or when allowing the user to “save progress” when going back a page, which could be desirable in registration flows and the like.

Navigation

Xamvvm also exposes a handful of interfaces that make observing page state a cinch. These Navigation Interceptions can be used individually or as groups to track the states you’re interested in. By added them to our ViewModel, we can get similar functionality to what we had in Prism.Forms:

Conclusion

We did it! That concludes our tour of ReactiveUI and Xamvvm in Xamarin.Forms. If you’re still craving Reactive goodies, the GitHub repo has an exhaustive sample for ReactiveUI (sans Xamvvm) specifically for Xamarin.Forms, and the handbook is a great resource. For the example used in this post, feel free to browse the complete source code, or leave a comment if you have questions! I’ll be publishing another post covering ReactiveUI in depth later on, so stay tuned

7 thoughts on “Bootstrap Series – Xamarin.Forms in ReactiveUI with Xamvvm

  1. Great workflows. Thanks
    With your gained expertice i mvvm Frameworks could you say if its possible to combine prism with reactiveui?

    Like

    1. I haven’t tried it myself, but it sounds doable – there would be some overlap (DelegateCommand vs ReactiveCommand), but can’t think of any direct conflicts. Let me try to whip up a sample and I’ll post a link 🙂

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s