Custom Navigation in MAUI MVVM

This section delves into advanced navigation scenarios beyond the standard patterns.

Introduction to Custom Navigation

While MAUI's built-in navigation handles most common use cases, complex applications often require more fine-grained control. Custom navigation allows you to define bespoke navigation logic, integrate with third-party navigation libraries, or implement unique user experiences.

When to Use Custom Navigation

Approaches to Custom Navigation

1. Using NavigationService with Custom Logic

The most common approach involves creating your own `NavigationService` class. This service encapsulates navigation methods and uses MAUI's underlying navigation APIs (like `INavigationService` or `Shell.Current.GoToAsync`) with custom parameters or logic.

Your ViewModel would then depend on this custom `NavigationService` and call its methods instead of directly invoking MAUI navigation.

Example: Custom Modal Presentation

Imagine you want to present a modal that slides in from the bottom with a specific animation. You can implement this using MAUI's `NavigationPage` and custom renderers, or by leveraging platform-specific APIs within your `NavigationService`.


// In your custom NavigationService
public async Task ShowCustomModalAsync(string route, object parameter = null)
{
    // Platform-specific logic to present modal with custom animation
    // For example, using a custom PageRenderer on each platform
    // or using Shell's GoToAsync with specific query parameters
    // that your custom page interprets.

    await Shell.Current.GoToAsync(route, parameter as IDictionary,
        animate: true); // May need to disable default animation and implement custom
}

// In your ViewModel
public class MyViewModel : BindableObject
{
    private readonly INavigationService _navigationService;

    public MyViewModel(INavigationService navigationService)
    {
        _navigationService = navigationService;
    }

    public ICommand ShowDetailsCommand => new Command(async () =>
    {
        await _navigationService.ShowCustomModalAsync("DetailsPage", new { Id = 123 });
    });
}
            

2. Direct Platform-Specific Navigation

For highly specialized scenarios, you might need to interact directly with native platform navigation APIs. This is typically done within platform-specific projects (e.g., `Platforms/iOS`, `Platforms/Android`) or via platform-specific implementations of an interface.

This approach can be more complex to maintain as it involves platform-specific code.

3. Event Aggregators and Messaging

For decoupled communication, especially when different parts of your application need to trigger navigation, an event aggregator (like MessagingCenter or a third-party library) can be useful. A component can publish a "NavigateToPage" event, and your central navigation handler can subscribe to it and perform the actual navigation.

Considerations for Custom Navigation

💡 Tip: Before implementing fully custom navigation, explore MAUI Shell's advanced features like flyouts, tabs, and custom route parameters. Often, these can satisfy complex requirements without resorting to extensive custom code.

Example: Navigating with a Custom Query Parameter

You can pass custom data as query parameters to `GoToAsync` and handle them in your target page's ViewModel.


// In ViewModel navigating
var parameters = new Dictionary
{
    { "userId", 42 },
    { "source", "ProfilePage" }
};
await Shell.Current.GoToAsync("UserDetailsPage", parameters);

// In UserDetailsPage ViewModel
[QueryProperty("UserId", "userId")]
[QueryProperty("Source", "source")]
public partial class UserDetailsViewModel : ObservableObject
{
    private string _userId;
    public string UserId
    {
        get => _userId;
        set => SetProperty(ref _userId, value);
    }

    private string _source;
    public string Source
    {
        get => _source;
        set => SetProperty(ref _source, value);
    }

    // ... other logic
}
            
Important: Be mindful of how you handle navigation events and ensure proper cleanup of resources, especially when dealing with complex or custom navigation flows.

Conclusion

Custom navigation in MAUI MVVM provides the flexibility to build sophisticated navigation experiences. By leveraging your own `NavigationService` and understanding MAUI's underlying navigation capabilities, you can create highly tailored and dynamic application flows.