Did you know that a poorly implemented navigation system is the #1 reason users abandon apps? That stat got my attention years ago, and ever since, I’ve made navigation a first-class citizen in every .NET MAUI project I touch. If you’ve ever struggled with making your app’s navigation feel smooth and intuitive, or wondered about passing data cleanly between pages, this guide is for you.
Let’s break down everything you need to know about navigation in .NET MAUI: from Shell to deep linking, and all the events in between.
Types of Navigation in .NET MAUI
.NET MAUI offers a few primary navigation models depending on how you structure your app.
Shell Navigation
Shell is the modern and recommended approach for .NET MAUI apps.
await Shell.Current.GoToAsync("//mainpage/details");
This command navigates to the Details page under the MainPage route. The //
prefix resets the navigation stack, ensuring clean forward-only navigation.
Why use Shell?
- URL-based routing
- Built-in flyout and tab support
- Declarative navigation structure
Flyout, Tabbed, and Stack Navigation
If you’re not using Shell, you can fall back to the traditional page-based navigation.
Flyout Page:
MainPage = new FlyoutPage
{
Flyout = new MenuPage(),
Detail = new NavigationPage(new HomePage())
};
Tabbed Page:
MainPage = new TabbedPage
{
Children = { new HomePage(), new SettingsPage() }
};
Stack Navigation:
await Navigation.PushAsync(new DetailsPage());
This is useful when you want a back-stack experience like a browser.
Passing Data Between Pages
There are two common patterns: query parameters (Shell) and constructor/property injection (non-Shell).
Using Query Parameters
Shell makes it easy to pass parameters via the URL:
await Shell.Current.GoToAsync($"details?id={item.Id}&name={item.Name}");
In your target page:
[QueryProperty("Id", "id")]
[QueryProperty("Name", "name")]
public partial class DetailsPage : ContentPage
{
public string Id { get; set; }
public string Name { get; set; }
}
Explanation: Decorate properties with QueryProperty
, matching them to the URL parameter name.
Navigating with Parameters in Shell
If you’re navigating with complex objects, serialize them to JSON:
string json = JsonSerializer.Serialize(myObject);
string encoded = Uri.EscapeDataString(json);
await Shell.Current.GoToAsync($"details?data={encoded}");
And in the destination page:
[QueryProperty("Data", "data")]
public partial class DetailsPage : ContentPage
{
public string Data { get; set; }
public MyModel Deserialized => JsonSerializer.Deserialize<MyModel>(Uri.UnescapeDataString(Data));
}
Deep Linking and Modal Navigation
Implementing Deep Linking
Shell supports deep links via URI handlers:
Routing.RegisterRoute("profile", typeof(ProfilePage));
Now, external links like myapp://profile
can open the page.
Working with Modal Pages
For modals (dialog-style full screens), use:
await Navigation.PushModalAsync(new ModalPage());
To close it:
await Navigation.PopModalAsync();
Tip: Modal pages do not integrate with the Shell navigation stack. They live in a separate stack.
4. Navigation Lifecycle Events
Knowing when a page appears or disappears helps manage resources and state.
Handling Appearing and Disappearing Events
protected override void OnAppearing()
{
base.OnAppearing();
Debug.WriteLine("Page is now visible");
}
protected override void OnDisappearing()
{
base.OnDisappearing();
Debug.WriteLine("Page is now hidden");
}
Managing Page States
For more complex scenarios (like pausing/resuming media or tracking analytics):
- Use these lifecycle methods
- Combine them with ViewModel logic to persist state
FAQ: Common Questions About .NET MAUI Navigation
It’s possible but not recommended. Shell manages its own stack, and mixing patterns can lead to inconsistent states.
Abstract navigation services behind an interface (e.g., INavigationService
) and mock them during tests.
PushAsync
is stack-based (traditional), while GoToAsync
is route-based (Shell).
Conclusion: Navigate Like a Pro in .NET MAUI
Mastering navigation is about more than moving between screens—it’s about creating fluid, intuitive journeys for your users. Whether you’re building a single-page experience or a tab-heavy monster, the tools in .NET MAUI have you covered.
Now, it’s your turn—revamp your navigation setup and watch your app’s UX go from “meh” to magic.
Still got questions? Drop a comment or check out the rest of the .NET MAUI deep dives on the blog.