MVVM Navigation in .NET MAUI

This section guides you through implementing navigation patterns in your .NET MAUI applications using the Model-View-ViewModel (MVVM) architecture.

Understanding Navigation in MAUI

.NET MAUI offers robust navigation capabilities that integrate seamlessly with the MVVM pattern. The primary mechanism for navigation is the INavigationService interface and its implementation provided by the framework. This service allows you to programmatically navigate between different pages or views in your application.

Common Navigation Scenarios

We'll explore several common navigation patterns:

  • Navigating to a new page.
  • Navigating back to a previous page.
  • Passing data between pages.
  • Modal navigation.
  • Tabbed navigation.
  • Flyout navigation (Hamburger menu).

Implementing Navigation Service

To effectively manage navigation within an MVVM application, it's recommended to abstract navigation logic into a dedicated service. This promotes loose coupling and makes your ViewModels more testable.

Here's a basic example of a INavigationService interface:

// Interfaces/INavigationService.cs
public interface INavigationService
{
void NavigateTo(string pageKey);
void NavigateTo(string pageKey, object parameter);
void GoBack();
void NavigateToModal(string pageKey);
void NavigateToModal(string pageKey, object parameter);
}

Registering Navigation Routes

Before you can navigate, you need to register your pages with the MAUI routing system. This is typically done in your application's startup code (e.g., MauiProgram.cs).

// MauiProgram.cs
public static MauiApp CreateMauiApp()
{
var builder = new MauiAppBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
})
.ConfigureRouting(() =>
{
Routing.RegisterRoute("HomePage", typeof(HomePage));
Routing.RegisterRoute("DetailsPage", typeof(DetailsPage));
Routing.RegisterRoute("ModalPage", typeof(ModalPage));
});

// Register your navigation service and ViewModels here
return builder.Build();
}

Navigating from a ViewModel

Inject the INavigationService into your ViewModel and use its methods to trigger navigation.

// ViewModels/MyViewModel.cs
public class MyViewModel : ObservableObject
{
private readonly INavigationService _navigationService;
private string _itemName;

public string ItemName
{
get => _itemName;
set => SetProperty(_itemName, value);
}

public ICommand NavigateCommand { get; }

public MyViewModel(INavigationService navigationService)
{
_navigationService = navigationService;
NavigateCommand = new RelayCommand(Navigate);
}

private void Navigate()
{
// Navigate to DetailsPage and pass ItemName as parameter
_navigationService.NavigateTo("DetailsPage", ItemName);
}
}

Receiving Data on the Destination Page

In the ViewModel of the destination page, you can retrieve the navigation parameter.

// ViewModels/DetailsViewModel.cs
public class DetailsViewModel : ObservableObject
{
private string _receivedData;

public string ReceivedData
{
get => _receivedData;
set => SetProperty(_receivedData, value);
}

public DetailsViewModel(INavigationService navigationService)
{
// MAUI's navigation service often handles parameter passing automatically when routing
// Or you can access it via Navigation.GetNavigationAsync(...)
// For simplicity, let's assume it's passed through constructor or property
// In a real scenario, you might use Navigation.GetNavigationAsync() or Dependency Injection
ReceivedData = navigationService.GetNavigationParameter()
// Hypothetical method to get parameter
}
}

Further Reading