Friday, October 18, 2019

Building A Cross Platform MVVM Pattern With ReactiveUI And Xamarin.Forms

As a mobile developer, when we start a new project, we always search for and speak about application architecture. One of the most common choices in Xamarin.Forms is MVVM. This is due to the small amount of work to implement it. If we use ReactiveUI, we can additionally write applications in a Reactive manner. It’s time to check the Reactive UI and how we can implement in Xamairn Forms project.
 
Reactive Extensions have been around for many years and are available to most development environments. In this post, we are specifically going to look at Rx in terms of .NET development in Xamarin Forms.
 
Rx is just a library for composing asynchronous, and event-based code with observables, and configuring it via LINQ. You can use LINQ to define criteria of when you want to perform an action, on the event. Rx can do more, but we will only look at the very basics in this post.
 
ReactiveUI allows you to combine the MVVM pattern with Reactive Programming using such features, as WhenAnyValue, ReactiveCommand, ObservableAsPropertyHelper, Binding and WhenActivated.
 
Building A Cross Platform MVVM Pattern With ReactiveUI And Xamarin.Forms 
 

Create New Xamarin.Forms Application

 
In order to learn the ReactiveUI, let’s start creating a new Xamarin.Forms project using Visual Studio 2019 or VS for Mac. When using Visual Studio 2019 on a Windows machine, you will need to pair the mac machine to run and build the iOS platform.
 
Open Visual Studio 2019 >>Create a New Project or select "Open Recent Application" and the available templates will appear on a window, like below. Select Xamarin.Forms app and click on “Next”.
 
Building A Cross Platform MVVM Pattern With ReactiveUI And Xamarin.Forms 
 

ReactiveUI Nuget Package

 
To implement ReactiveUI in our application, we will need to install the library.
 
Step 1
 
Right-click on Project and click on the "Manage NuGet Packages for Solution" option.
 
Step 2
 
Search for “ReactiveUI.XamForms”.
 
Step 3
 
Install it for all of our projects with each platform.
 
Building A Cross Platform MVVM Pattern With ReactiveUI And Xamarin.Forms 
 

Create ViewModel

 
ReactiveUI syntax for read-write properties is to notify the Observers that a property has changed. Otherwise, we would not be able to know when it was changed.
  • In cases when we don't need to provide a two-way binding between the View and the ViewModel, we can use one of many ReactiveUI Helpers, to notify the Observers of changing the read-only value in the ViewModel.
  • RaiseAndSetIfChanged fully implements a Setter for a read-write property on a ReactiveObject, using CallerMemberName to raise the notification and the ref to the backing field to set the property.
  • ReactiveCommand is a Reactive Extensions and asynchronous aware implementation of the ICommand interface. ICommand is often used in the MVVM design pattern to allow the View to trigger business logic defined in the ViewModel
Let us create the following property and command in the following ViewModel.
  1. using System;  
  2. using System.Threading.Tasks;  
  3. using ReactiveUI;  
  4. using System.Reactive;  
  5. using System.Text.RegularExpressions;  
  6. using System.Collections.Generic;  
  7. using System.Reactive.Linq;  
  8.   
  9. namespace ReactiveUIXamarin.ViewModel  
  10. {  
  11.     public class MainPageViewModel: ReactiveObject  
  12.     {  
  13.         private string _result;  
  14.         public string Result  
  15.         {  
  16.             get => _result;  
  17.             set => this.RaiseAndSetIfChanged(ref _result, value);  
  18.         }  
  19.         private string _username;  
  20.         public string UserName  
  21.         {  
  22.             get => _username;  
  23.             set => this.RaiseAndSetIfChanged(ref _username, value);  
  24.         }  
  25.         private string _password;  
  26.         public string Password  
  27.         {  
  28.             get => _password;  
  29.             set => this.RaiseAndSetIfChanged(ref _password, value);  
  30.         }  
  31.         private string _address;  
  32.         public string Address  
  33.         {  
  34.             get => _address;  
  35.             set => this.RaiseAndSetIfChanged(ref _address, value);  
  36.         }  
  37.         private string _phone;  
  38.         public string Phone  
  39.         {  
  40.             get => _phone;  
  41.             set => this.RaiseAndSetIfChanged(ref _phone, value);  
  42.         }  
  43.         public ReactiveCommand<Unit, Unit> RegisterCommand { get; }  
  44.   
  45.         public MainPageViewModel()  
  46.         {  
  47.             RegisterCommand = ReactiveCommand  
  48.                 .CreateFromObservable(ExecuteRegisterCommand);  
  49.         }  
  50.   
  51.         private IObservable<Unit> ExecuteRegisterCommand()  
  52.         {  
  53.             Result = "Hello" + UserName + " Registration Success";  
  54.             return Observable.Return(Unit.Default);  
  55.         }  
  56.     }    
  57. }  

Create UI View

 
ReactiveUI allows you to create views using two different approaches. The recommended approach is using type-safe ReactiveUI bindings that can save you from memory leaks and runtime errors. The second approach is using XAML markup bindings.
 
The following sample UI created by the recommended approach using type-safe ReactiveUI. 
  1. <rxui:ReactiveContentPage  
  2.   x:Class="ReactiveUIXamarin.MainPage"  
  3.   x:TypeArguments="vm:MainPageViewModel"            
  4.   xmlns:vm="clr-namespace:ReactiveUIXamarin.ViewModel;assembly=ReactiveUIXamarin"  
  5.   xmlns:rxui="clr-namespace:ReactiveUI.XamForms;assembly=ReactiveUI.XamForms"  
  6.   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"  
  7.   xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"   
  8.   xmlns="http://xamarin.com/schemas/2014/forms"  
  9.     ios:Page.UseSafeArea="true">  
  10.     <StackLayout>  
  11.         <Entry x:Name="Username" Placeholder="Username"/>  
  12.         <Entry x:Name="Password" Placeholder="Password"  />  
  13.         <Entry x:Name="Address" Placeholder="Address"  />  
  14.         <Entry x:Name="Phone" Placeholder="Phone Number" />  
  15.         <Button x:Name="Register" Text="Register" TextColor="White" BackgroundColor="Gray" />  
  16.         <Label x:Name="Result" />  
  17.     </StackLayout>  
  18. </rxui:ReactiveContentPage>  
  • ContentPage should inherit from ReactiveContentPage<TViewModel> and we are going to use ReactiveUI Binding to bind our ViewModel to our View.
  • Reactive binding is a cross-platform way of consistently binding properties on your ViewModel to controls on your View.
  • The ReactiveUI binding has a few advantages over the XAML based binding. The first advantage is that property name changes will generate a compile error rather than runtime errors.
  • One important thing needed to be followed while the binding is that you always dispose of the bindings via WhenActivated, or else the bindings leak memory.
    1. using ReactiveUI;  
    2. using System;  
    3. using System.Collections.Generic;  
    4. using System.ComponentModel;  
    5. using System.Linq;  
    6. using System.Text;  
    7. using System.Threading.Tasks;  
    8. using Xamarin.Forms;  
    9. using ReactiveUIXamarin.ViewModel;  
    10. using ReactiveUI.XamForms;  
    11. using System.Reactive.Disposables;  
    12.   
    13. namespace ReactiveUIXamarin  
    14. {  
    15.   
    16.     public partial class MainPage : ReactiveContentPage<MainPageViewModel>  
    17.     {  
    18.         public MainPage()  
    19.         {  
    20.             InitializeComponent();  
    21.             ViewModel = new MainPageViewModel();  
    22.   
    23.             // Setup the bindings.  
    24.             // Note: We have to use WhenActivated here, since we need to dispose the  
    25.             // bindings on XAML-based platforms, or else the bindings leak memory.  
    26.             this.WhenActivated(disposable =>  
    27.             {  
    28.                 this.Bind(ViewModel, x => x.UserName, x => x.Username.Text)  
    29.                     .DisposeWith(disposable);  
    30.                 this.Bind(ViewModel, x => x.Password, x => x.Password.Text)  
    31.                     .DisposeWith(disposable);  
    32.                 this.Bind(ViewModel, x => x.Address, x => x.Address.Text)  
    33.                    .DisposeWith(disposable);  
    34.                 this.Bind(ViewModel, x => x.Phone, x => x.Phone.Text)  
    35.                    .DisposeWith(disposable);  
    36.                 this.BindCommand(ViewModel, x => x.RegisterCommand, x => x.Register)  
    37.                     
    38.                     .DisposeWith(disposable);  
    39.                 this.Bind(ViewModel, x => x.Result, x => x.Result.Text)  
    40.                    .DisposeWith(disposable);  
    41.             });  
    42.         }  
    43.     }  
    44. }  
Output
 
You can download the source code from the GitHub repository. When you run the application in an iPhone device, you will get the following output. Click on "Register"; it will show the confirmation message like below.
 
Building A Cross Platform MVVM Pattern With ReactiveUI And Xamarin.Forms

No comments:

Post a Comment

No String Argument Constructor/Factory Method to Deserialize From String Value

  In this short article, we will cover in-depth the   JsonMappingException: no String-argument constructor/factory method to deserialize fro...