Exrin 2.0.0 Quick Start

With the first release of Exrin 2.0.0, it is now easier to build Exrin apps, while still gaining all the benefits. Exrin 2.0.0 is backward compatible with 1.x. I will now go through how to create an Exrin app, in the quickest way possible. A pre-built sample QuickStart app is available on Github, if you wish to follow along.

Xamarin Forms App

Create a new Xamarin Forms App, using Portable (PCL).

Note: This unfortunately doesn’t create a .NET Standard app, you can use my sample, if you want a .NET Standard Xamarin Forms app.

Nuget Packages

After you have created a new Xamarin Forms app, it’s generally a good idea, to update to the latest Xamarin Forms Nuget package. Also for this example, you will want to install AutoFac, as we will use this for our Dependency Injection. If you are using .NET Standard, it is a good idea to use Xamarin.Forms 2.3.5 or above.

Proxies

The first thing we need to do, is copy across some proxy classes. This is just a once off, but these classes are what enable Exrin to have zero dependencies. You can run any version of Exrin, with any version of Xamarin Forms, with any version of your preferred dependency injection framework.

InjectionProxy
This connects to your Dependency Injection framework, in this example, AutoFac.

NavigationProxy
This connects to the Xamarin Forms NavigationPage.

PageProxy
This is a ContentPage, implementing IView. All ContentPages in your app must inherit from here.

Place these in your Proxy folder in your Portable Library.

Bootstrapper

This is the service that starts everything up, including setting the MainPage. Create a new Bootstrapper class and copy the code as below. This will also find all Views, ViewModels, Models and Service and automatically create an instance of them when applicable.

public class Bootstrapper : Exrin.Framework.Bootstrapper
{ 
    private static Bootstrapper _instance = null; 
    public Bootstrapper(IInjectionProxy injection, Action<object> setRoot, Func<object> getRoot) : base(injection, setRoot, getRoot) { }

     public static Bootstrapper GetInstance() 
     { 
         if (_instance == null) 
             _instance = new Bootstrapper(new Injection(), (view) => Application.Current.MainPage = view as Page, () => { return Application.Current.MainPage; });

         return _instance; 
     }
}

 

Locator

The locator class is just a place to enter keys for referencing your Stacks and Views. Stacks are just a collection of related views. E.g. A LoginStack, and an AppStack, that contains all the views of your app when you are logged in. You can create as many or as little stacks as you want.

// These are keys that identify your stacks and views. You can use Enums, or Strings, whatever takes your fancy.
public enum Stacks { App }

public enum AppViews { Main, About }

Initialization

In our App.cs, we want to remove the setting of the MainPage and place the following code.

public App() 
{ 
    InitializeComponent();
    // If you want to set specific platform only options, move this to each native platform project 
    Exrin.Framework.App.Init();

    // Everything is setup, and the MainPage is set here 
    Bootstrapper.GetInstance() 
                .Init() 
                .Get<INavigationService>() 
                .Navigate(new StackOptions() 
                { 
                    StackChoice = Stacks.App 
                }); 
}

You will notice that your reference a stack here. This is your starting stack. We will go into how to create a stack shortly.

Views

When you create a new ContentPage, you need to go and inherit from your PageProxy. Everything else remains the same. Here is an example.

<?xml version="1.0" encoding="utf-8" ?>
<proxy:PageProxy xmlns="http://xamarin.com/schemas/2014/forms"             
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
                 xmlns:proxy="clr-namespace:ExrinQuickStart.Proxy"             
                 x:Class="ExrinQuickStart.Views.MainPage"     
                 Title="Home">    
    <ContentPage.Content>        
        <StackLayout>            
            <Label Text="Welcome to Xamarin Forms!" /> 
            <Button Text="Navigate To About Page" Command="{Binding AboutCommand}" />
       </StackLayout>    
    </ContentPage.Content>
</proxy:PageProxy>

ViewModels

You must inherit your ViewModels from Exrin.Framework.ViewModel. From here you have a lot of navigation overrides available to you. Have a look at ViewModel overrides in The Advanced Navigation of Exrin in Xamarin Forms.

For properties, use the Get and Set functions to deal with INotifyPropertyChanged, and you can also see an example of a Command.

public class MainViewModel : Exrin.Framework.ViewModel 
{ 
    // One ViewModel per View is recommended but not enforced.
    private readonly IAppModel _model;
    public MainViewModel(IAppModel model) 
    { 
        _model = model; 
    }
    // Using the special Get and Set methods will ensure INotifyPropertyChanged is implemented. 
    public string HelloText { get { return Get<string>(); } set { Set(value); } }

    public IRelayCommand NavigationCommand 
    { 
        get 
        { 
            return GetCommand(() => 
            {
                return new RelayCommand(async (parameter) => 
                { 
                    await NavigationService.Navigate(nameof(AppViews.About)); 
                }); 
            }); 
        }  
    }
}

You also have the optional use of putting properties like HelloText, into their own VisualState class. I go into this, in the Extras section below.

Models

Models hold your business logic. They just need to inherit from Exrin.Framework.Model. If you create your own interface, ensure it inherits off IBaseModel.

public interface IAppModel: IBaseModel { }
public class AppModel : Exrin.Framework.Model, IAppModel 
{
    // Business Logic goes in here 
    // You also access your services or repositories through here
}

Stacks

Stacks are the final piece that connect everything together. Here you pass through your NavigationProxy, Stack name, and the default first page of the stack, by the Locator keys. Then you can Map each Page, to ViewModel and assign a key to that page. These keys are what you use, when navigating.

public class AppStack : BaseStack 
{ 
    public AppStack(IViewService viewService) : base(new NavigationProxy(), viewService, Stacks.App, nameof(AppViews.Main)) 
    { 
        ShowNavigationBar = true; 
    }

    protected override void Map() 
    {
        base.NavigationMap<MainPage, MainViewModel>(nameof(AppViews.Main)); 
        base.NavigationMap<AboutPage, AboutViewModel>(nameof(AppViews.About)); 
    }
}

And that’s it. Your app will now run.

Extra

There are some extra pieces of information, you might want to note.

VisualState

VisualState, is just a separate class, you can use to store properties that are bound to your View. While optional, I do recommend using them as you will gain a few benefits, such as an autowireup of matching property names in your Model to ViewModel. Also this is required if you are to use the Exrin Inspector.

public class MainVisualState : Exrin.Framework.VisualState 
{ 
    public MainVisualState(IAppModel model) : base(model) { }

    public string HelloText { get { return Get<string>(); } set { Set(value); } } }
}

public class MainViewModel : Exrin.Framework.ViewModel 
{
    private readonly IAppModel _model; 
    public MainViewModel(IAppModel model) : base(new MainVisualState(model)) 
    {
        _model = model; 
    }
}

Then in your View, you just need to reference the property by going Text=”{Binding VisualState.HelloText}”.

Operations

Operations, wrap a RelayCommand, with prevention for running at the same time, moving it to the background thread, and timeouts. These are optional, however they are very useful, as you don’t want to run a command twice in quick succession, or run on the UI Thread. Instead of repeating code to do this for every command, you can use an operation.

public IRelayCommand AboutCommand 
{ 
    get 
    { 
        return GetCommand(() => 
        { 
            return Execution.ViewModelExecute((parameter, token) => 
            { 
                return new NavigationResult(AppViews.About); 
            }); 
        }); 
    } 
}
Microsoft MVP | Xamarin MVP | Xamarin Certified Developer |
Exrin MVVM Framework | Xamarin Forms Developer | Melbourne, Australia

Related Posts

Leave A Comment?