Navigation Parameters in MAUI

Learn how to pass data between pages using navigation parameters in .NET MAUI applications.

When building a .NET MAUI application, you often need to pass data from one page to another. This is commonly done when navigating to a detail page for a specific item or when passing configuration settings. .NET MAUI provides a robust mechanism for passing parameters during navigation.

Passing Parameters During Navigation

The primary way to pass parameters is by adding them to the route when navigating. This is typically done when using the Shell.Current.GoToAsync method.

Using Named Routes

You can define routes with placeholders for parameters. For example, a route like DetailsPage/{id} indicates that an id parameter is expected.

Tip: Using named routes with parameters makes your navigation logic cleaner and more maintainable.
// In your ViewModel or Code-Behind
await Shell.Current.GoToAsync($"DetailsPage?itemId={selectedItem.Id}");

Using Query Parameters

An alternative is to use query parameters, which are appended to the URI after a question mark (?).

await Shell.Current.GoToAsync($"DetailsPage?productId=123&category=electronics");

Receiving Parameters on the Destination Page

On the page you are navigating to, you can access these parameters using the Shell.Current.Navigation.GetNavigationArgs() method or by utilizing query string parsing.

Accessing Parameters with NavigationEventArgs

When navigation occurs, an event is raised. You can subscribe to this event or handle it within the page's lifecycle methods to retrieve parameters.

A common pattern is to use an overload of GoToAsync that accepts an IDictionary<string, object>:

// Navigating
var parameters = new Dictionary
{
    { "UserId", 42 },
    { "UserName", "JaneDoe" }
};
await Shell.Current.GoToAsync("UserProfilePage", parameters);

On the destination page, you can retrieve these parameters within the OnNavigatingTo or OnNavigatedTo methods:

public partial class UserProfilePage : ContentPage
{
    public UserProfilePage()
    {
        InitializeComponent();
    }

    protected override void OnNavigatingTo(NavigatingEventArgs args)
    {
        base.OnNavigatingTo(args);

        // Accessing parameters passed via dictionary
        if (args.Navigation.NavigationStack.LastOrDefault()?.Navigation.NavigationArgs != null)
        {
            var parameters = args.Navigation.NavigationStack.LastOrDefault()!.Navigation.NavigationArgs;
            if (parameters.TryGetValue("UserId", out object userId))
            {
                UserId = (int)userId;
            }
            if (parameters.TryGetValue("UserName", out object userName))
            {
                UserName = userName.ToString();
            }
        }
    }

    public int UserId { get; set; }
    public string UserName { get; set; }
}

Receiving Query Parameters Directly

If you use query parameters in the route string, you can parse them directly from the URI.

protected override async void OnNavigatedTo(NavigatedToEventArgs args)
{
    base.OnNavigatedTo(args);

    // Example: Navigating with "DetailsPage?productId=123"
    // This approach might require manual parsing of the URI
    var currentUri = Shell.Current.CurrentPage?.GetValue(Shell.NavigationViewProperty)?.GetValue(Shell.NavigationStateProperty)?.ToString();

    if (!string.IsNullOrEmpty(currentUri) && currentUri.Contains("?"))
    {
        var query = System.Web.HttpUtility.ParseQueryString(new Uri(currentUri).Query);
        if (query["productId"] != null)
        {
            int productId = int.Parse(query["productId"]);
            // Load product details using productId
        }
    }
}
Note: The direct URI parsing can be fragile. Using the dictionary approach is generally recommended for robustness.

Passing Complex Objects

While you can't directly pass complex objects as route parameters, you can pass unique identifiers (like IDs) and then use these identifiers on the destination page to fetch the full object from a data service or repository.

Alternatively, you can serialize complex objects into strings (e.g., JSON) and pass them as string parameters, then deserialize them on the receiving end. However, this approach should be used cautiously, especially for large objects, due to potential performance implications and URI length limits.

// Example: Passing a serialized object (use with caution)
var product = new Product { Id = 1, Name = "Example", Price = 19.99 };
var jsonProduct = System.Text.Json.JsonSerializer.Serialize(product);
await Shell.Current.GoToAsync($"ProductDetailsPage?productData={System.Net.WebUtility.UrlEncode(jsonProduct)}");

On the destination page:

protected override void OnNavigatedTo(NavigatedToEventArgs args)
{
    base.OnNavigatedTo(args);

    if (args.Navigation.NavigationStack.LastOrDefault()?.Navigation.NavigationArgs != null &&
        args.Navigation.NavigationStack.LastOrDefault()!.Navigation.NavigationArgs.TryGetValue("productData", out object productData))
    {
        var jsonProduct = System.Net.WebUtility.UrlDecode((string)productData);
        var product = System.Text.Json.JsonSerializer.Deserialize<Product>(jsonProduct);
        // Use the deserialized product object
    }
}

Best Practices

By effectively utilizing navigation parameters, you can create more dynamic and data-rich experiences in your .NET MAUI applications.

Tags: .NET MAUI Navigation Tutorial C# Mobile Development Cross-Platform