Home

Awesome

CodeMill ViewModel First Navigation Library

A Xamarin.Forms ViewModel First Navigation Library

Build Status

NuGet

CodeMill.VMFirstNav

Installation

The installation is pretty straight forward - head on out to NuGet and search for CodeMill.VMFirstNav. Or you could run Install-Package CodeMill.VMFirstNav from the package manager console.

At this time, this package will need to be installed into both the platform and core projects.

The library is .netstandard1.0 with a dependency on Xamarin.Forms 2.3.4.247 and above.

The API

There are 3 main interfaces that are a part of this library.

IViewModel and IViewFor<T> are used to associate a view->view model pair.

IViewModel is nothing but a marker interface and should be put onto every view model class that is to participate in VM first navigation.

IViewFor<T> goes onto the Pages that are associated with the view model - the T will be the IViewModel it is associated with. There is one property that must be implemented: T ViewModel { get; set; }

In a class that implements IViewFor<ChildViewModel> I would recommend implementing that property as follows:

ChildViewModel vm;
public ChildViewModel ViewModel { 
    get => vm; 
    set
    {
        vm = value;
        BindingContext = vm;
    }
}

Initialization

At runtime , the library will take care of finding the view -> view-model pairs when RegisterViewModels is called and it's passed the assembly of where the views and view models live. (Currently they have to both be in the same assembly).

You would do this in either the AppDelegate or MainActivity class:

NavigationService.Instance.RegisterViewModels(typeof(App).Assembly);

As you may have noted above - everything runs through a class called NavigationService. You don't instantiate it directly, because it needs to keep track of that internal view->view model dictionary, but rather accessed through a singleton called Instance. This way it'll stay in memory for the life of the app.

It conforms to another interface called INavigationService whose definition looks like the following:

public interface INavigationService
{
    void RegisterViewModels(System.Reflection.Assembly asm);
    void Register(Type viewModelType, Type viewType);

    Task PopAsync();
    Task PopAsync<T>(Action<T> reInitialize = null) where T : class, IViewModel;
    Task PopModalAsync();
    void PopTo<T>() where T : class, IViewModel;
    Task PopToRootAsync(bool animate);
    
    Task PushAsync<T>(T viewModel) where T : class, IViewModel;
    Task PushAsync<T>(Action<T> initialize = null) where T : class, IViewModel;
    Task PushModalAsync<T>(T viewModel) where T : class, IViewModel;
    Task PushModalAsync<T>(Action<T> initialize = null) where T : class, IViewModel;
       
    void SwitchDetailPage<T>(T viewModel) where T : class, IViewModel; 
    void SwitchDetailPage<T>(Action<T> initialize = null) where T : class, IViewModel;    
}

As I break these down one by one - when I refer to a view->view model combination being on the stack, I'm really only referring to the view (or Page) residing in the Xamarin.Forms INavigation.NavigationStack and then being able to find it's associated view model via the internal dictionary. So... instead of saying that... it's easier to refer to them as both being on the stack.

Registration

Popping

Pushing

Switching

Used with MasterDetailPages to switch the MasterDetailPage.Detail page or the App.MainPage.

A Word On Master/Detail Pages

The library also provides a class to help with MasterDetailPages when the master page is composed of a list with options that when selected open a new list. MasterListItem<T>. It contains one property, DisplayName that is meant for display in the ListView, and the T is the IViewModel.

The idea here is that when the item gets selected from the ListView, you'll have a MasterListItem<T> class. From that you can create extract the T, new up the view model, and then swap the Detail page.