Skip to content

Navigation

Jan M edited this page Nov 20, 2020 · 17 revisions

Intro

Prerequisites

An IDependencyContainer has to be registered in order to use the NavigationService.
The IDependencyContainer is used to create the ViewModel instances.

ViewModels you want to register in navigation routes have to implement the interface IViewModel.
Note: Implementing our ViewModelBase does suffice.

Setup

Logging can be enabled calling NavigationService.SetupLogging(myLogServiceInstance).

Registration

You can either pass an INavigationRegistration instance or register ViewModels and Views using generic methods from the ViewModelNavigationServiceExtensions

Using the INavigationRegistration class

public interface INavigationRegistration
{
    Type ViewModelType { get; }
    Type ViewType { get; }

    bool ResolveViewUsingDependencyInjection { get; set; }

    bool PreCreateInstance { get; set; }


    Func<bool> Condition { get; set; }
}

First, you create your NavigationRegistration instance containing the values you want to register, e.g.:

var registration = new NavigationRegistration(
    typeof(IMainViewModel),
    typeof(MainView));

Afterwards, you just pass this instance into the navigation service, calling
public void Register(INavigationRegistration registrationInfo):

navigationService.Register(registration);

You can also use the generic registration method. This method creates a default INavigationRegistration (don't use DI, don't pre-create, no condition), but you can use the extension methods afterwards.

public INavigationRegistration Register<TViewModel, TView>()  
    where TViewModel : IViewModel  
    where TView : class
navigationService.Register<IMainViewModel, MainView>();

To add a specific condition:

navigationService.Register<LocationViewModel, LocationView>()
    .WithCondition(() => service.IsGpsAvailable);

Using the extension methods

The extension methods provide registration functionality in fluent style: navigationService.Register<MainViewModel, MainView>() .WithCondition(MethodReturningBool);

Navigating

When you want to navigate from one ViewModel to another, you just have to resolve the INavigationService instance in your ViewModel and call
public virtual async Task ShowAsync<TDestinationViewModel>()

public class MainViewModel :
    IViewModel
{
    private readonly INavigationService _navigationService;

    public ICommand ShowSettingsCommand { get; }


    public MainViewModel(
        INavigationService navigationService)
    {
        _navigationService = navigationService;

        ShowSettingsCommand = new AsyncCommand(
            _navigationService.ShowAsync<SettingsViewModel>);
    }
}

Passing parameters

In many cases you have or want to pass values from one ViewModel to another when navigating.
With CodeMonkeys, this is possible implementing the IViewModel<T> interface, where T is the type of data your ViewModel depends on.
For those ViewModels you can use the navigation method that allows passing parameters:
public virtual async Task ShowAsync<TDestinationViewModel, TData>(TData data)

Example

public class LoginViewModel :
    IViewModel
{
    private readonly INavigationService _navigationService;
    private readonly ILoginService _loginService;

    public string UserName { get; set; }
    public string Password { get; set; }

    public ICommand LoginCommand => new AsyncCommand(LoginAsync);

    public LoginViewModel(
        INavigationService navigationService,
        ILoginService loginService)
    {
        _navigationService = navigationService;
        _loginService = loginService;
    }
    
    private async Task LoginAsync()
    {
        if (_loginService.TryLoginAsync(
            UserName,
            Password,
            out LoginResult loginResult)
        {
            await _navigationService.ShowAsync<MainViewModel, User>(
                loginResult.User);
        }

        // some error handling        
    }
}

public class MainViewModel :
    IViewModel<User>
{
    ...
}

When navigation occurs, the destination ViewModel is resolved and InitializeAsync<T> is called on it, passing the parameter from ShowAsync<TViewModel, TData>.

Clone this wiki locally