TinyNavigationHelper for Xamarin.Forms

TinyNavigationHelper is a helper that I created together with Johan Karlsson for a project where I don’t want to install a separate MVVM framework, but I still wanted to have an abstraction for the Navigation so that I could handle navigation in my ViewModels without having a reference to Xamarin.Forms in the ViewModels. The reason for that is that I want to have my ViewModels clean from platform specific libraries so I can use them for other platforms as well, for example, if I want to extend my application with support for WPF.

You will find the source code on GitHub and you’re more than welcome to contribute and give feedback.
https://github.com/dhindrik/TinyNavigationHelper. You will also find the complete documentation on GitHub.

Installation
The easiest way to install it is via NuGet:
Install-Package TinyNavigationHelper.Forms

And for projects that not reference Xamarin.Forms:
Install-Package TinyNavigationHelper.Abstraction

Configure TinyNavigationHelper
There are three ways to configure the navigation, the two first is to register the type of the view together with a key that you define. The third way is to register all views in an assembly. What the method will do that it searching throw the assembly for classes that inherit from Page.

// Option 1: Register single views
var navigationHelper = new FormsNavigationHelper(this);
navigationHelper.RegisterView("MainView");
 
// Option 2: Register single views
var navigationHelper = new FormsNavigationHelper(this);
navigationHelper.RegisterView("MainView", typeof(MainView));
 
// Option 3: Register all views (pages) that is inherited from Page
// The class name will be the key. To use this, you need to add using System.Reflection;
var asm = typeof(App).GetTypeInfo().Assembly;
navigationHelper.RegisterViewsInAssembly(asm);

If you want to use it with dependency injection you can register FormsNavigationHelper with the INavigationHelper interface.

Use TinyNavigationHelper
You can always get the current instance of TinyNavigationHelper via the static Current property on from the NavigationHelper class.

var navigationHelper = NavigationHelper.Current;

To navigate to a view, use the NavigateToAsync method.

await navigationHelper.NavigateToAsync("MainView");
 
//With parameter
await navigationHelper.NavigateToAsync("MainView", "Parameter");

The parameter will be sent to the constructor of the view.

public class MainView
{
     public MainView(object parameter)
     {
          var data = parameter as string;
     }
}

To go back, use the BackAsync method.

await navigationHelper.BackAsync();

You can also open a modal with the OpenModalAsync method.

await navigationHelper.OpenModalAsync("MainView");
 
//open a modal with an own navigation page
await navigationHelper.OpenModalAsync("MainView", true);
 
//with parameter
await navigationHelper.OpenModalAsync("MainView", "parameter", true);

You will close the modal with the CloseModalAsync method.

await navigationHelper.CloseModalAsync();

If you want to reset the navgation stack, you can use the SetRootView method.

//without parameter and navigation stack
navigationHelper.SetRootView("MainView");
 
//with parameter, but without navigation stack
navigationHelper.SetRootView("MainView", "parameter");
 
//without parameter, but with navigation stack
navigationHelper.SetRootView("MainView", true);
 
//with parameter and navigation stack
navigationHelper.SetRootView("MainView", "parameter", true);

Xamarin.Forms – MVVM BaseView and BaseViewModel

In this post, I will describe how I have created base classes for my views and ViewModels in my latest projects. It will probably break some of the MVVM rules, but I think this is a productive way to work. Please leave a comment about your thoughts about in a comment below.

First of all, I’m creating the base ViewModel. I’m adding three virtual methods, Init, OnAppearing and OnDisappering. I’m making the methods virtual so I can override them in the view models if I want.

My idea is that Init() will run after the ViewModel has been created. OnAppearing when a view appearing on the screen and disappearing when the view is disappearing. To place them in the base class for the view models makes it possible to call them from a base class for my views so I don’t have to write code for calling them in every view I’m creating.

If I using an MVVM framework (I’m used to using MvvmLight) my base ViewModel will inherit the base ViewModel from the framework I’m using. But this example will show how it will be without any framework.

public abstract class BaseViewModel : INotifyPropertyChanged
{
     public event PropertyChangedEventArgs PropertyChanged;
 
     public async virtual Task Init()
     {
     }
 
     public async virtual Task OnAppearing()
     {
     }
 
     public async virtual Task OnDisappearing()
     {
     }
}

My base view will be generic to define what ViewModel I will use for the current view. I will also say the generic type has to inherit from BaseViewModel so it not can be used with other types of object. This also makes it possible for me to call the methods I created in the BaseViewModel. In the constructor, I will use my IoC to create an instance of the ViewModel.

public abstract class BaseView<T> : ContentPage where T : BaseViewModel
{
 
     private BaseViewModel _viewModel;
 
     public BaseView()
     {
         //IoCHelper is an own defined class for resolving types that are defined in an IoC container
         _viewModel = IoCHelper.Resolve<T>();
 
         BindingContext = _viewModel;
 
         viewModel.Init();       
     }
 
     public async override void OnAppearing()
     {
           base.OnAppearing();
 
          await _viewModel.OnAppearing();
     }
 
     public async override void OnDisappearing()
     {
          base.OnDisappering();
 
          await _viewModel.OnDisappering();
     }
}

To define what ViewModel that should be used for the view in XAML you can do that by using x:TypeArguments like in the example below. This means that you don’t have to write any code in the code-behind. Don’t forget to remove that the view inherits from ContentPage in the code-behind of the view.

<local:BaseView xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:MyApp.Views;"
             xmlns:vm="clr-namespace:MyAPp.ViewModels;"
             x:TypeArguments="vm:MainViewModel"
             x:Class="MyApp.Views.MainView">