$npx -y skills add managedcode/dotnet-skills --skill maui-shell-navigationGuide for implementing Shell-based navigation in .NET MAUI apps. Covers AppShell setup, visual hierarchy (FlyoutItem, TabBar, Tab, ShellContent), URI-based navigation with GoToAsync, route registration, query parameters, back navigation, flyout and tab configuration, navigation e
| 1 | # .NET MAUI Shell Navigation |
| 2 | |
| 3 | Implement page navigation in .NET MAUI apps using Shell. Shell provides URI-based navigation, a flyout menu, tab bars, and a four-level visual hierarchy — all configured declaratively in XAML. |
| 4 | |
| 5 | ## When to Use |
| 6 | |
| 7 | - Setting up top-level app navigation with tabs or a flyout menu |
| 8 | - Navigating between pages programmatically with `GoToAsync` |
| 9 | - Passing data between pages via query parameters or object parameters |
| 10 | - Registering detail-page routes for push navigation |
| 11 | - Guarding navigation with confirmation dialogs (e.g., unsaved changes) |
| 12 | - Customizing back button behavior per page |
| 13 | |
| 14 | ## When Not to Use |
| 15 | |
| 16 | - Deep linking from external URLs or app links — see [.NET MAUI deep linking docs](https://learn.microsoft.com/dotnet/maui/fundamentals/app-links) |
| 17 | - Data binding on navigation target pages — use `maui-data-binding` |
| 18 | - Dependency injection for pages and view models — use `maui-dependency-injection` |
| 19 | - Apps using `NavigationPage` without Shell (different navigation API) |
| 20 | |
| 21 | ## Inputs |
| 22 | |
| 23 | - A .NET MAUI project with `AppShell.xaml` as the root shell |
| 24 | - Pages (`ContentPage`) to navigate between |
| 25 | - Route names for detail pages not in the visual hierarchy |
| 26 | |
| 27 | ## Shell Visual Hierarchy |
| 28 | |
| 29 | Shell uses a four-level hierarchy. Each level wraps the one below it: |
| 30 | |
| 31 | ``` |
| 32 | Shell |
| 33 | ├── FlyoutItem / TabBar (top-level grouping) |
| 34 | │ ├── Tab (bottom-tab grouping) |
| 35 | │ │ ├── ShellContent (page slot → ContentPage) |
| 36 | │ │ └── ShellContent (multiple = top tabs) |
| 37 | │ └── Tab |
| 38 | └── FlyoutItem / TabBar |
| 39 | ``` |
| 40 | |
| 41 | - **FlyoutItem** — appears in the flyout menu; contains `Tab` children |
| 42 | - **TabBar** — bottom tab bar with no flyout entry |
| 43 | - **Tab** — groups `ShellContent`; multiple children produce top tabs |
| 44 | - **ShellContent** — each points to a `ContentPage` |
| 45 | |
| 46 | ### Implicit Conversion |
| 47 | |
| 48 | You can omit intermediate wrappers. Shell auto-wraps: |
| 49 | |
| 50 | | You write | Shell creates | |
| 51 | |------------------------------|---------------------------------------| |
| 52 | | `ShellContent` only | `FlyoutItem > Tab > ShellContent` | |
| 53 | | `Tab` only | `FlyoutItem > Tab` | |
| 54 | | `ShellContent` in `TabBar` | `TabBar > Tab > ShellContent` | |
| 55 | |
| 56 | ## Workflow: Set Up AppShell |
| 57 | |
| 58 | 1. Define `AppShell.xaml` inheriting from `Shell` |
| 59 | 2. Add `FlyoutItem` or `TabBar` elements for top-level navigation |
| 60 | 3. Add `Tab` elements for bottom tabs; nest multiple `ShellContent` for top tabs |
| 61 | 4. **Always use `ContentTemplate`** with `DataTemplate` so pages load on demand |
| 62 | 5. Register detail-page routes in the `AppShell` constructor |
| 63 | |
| 64 | ```xml |
| 65 | <Shell xmlns="http://schemas.microsoft.com/dotnet/2021/maui" |
| 66 | xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
| 67 | xmlns:views="clr-namespace:MyApp.Views" |
| 68 | x:Class="MyApp.AppShell" |
| 69 | FlyoutBehavior="Flyout"> |
| 70 | |
| 71 | <FlyoutItem Title="Animals" Icon="animals.png"> |
| 72 | <Tab Title="Cats"> |
| 73 | <ShellContent Title="Domestic" |
| 74 | ContentTemplate="{DataTemplate views:DomesticCatsPage}" /> |
| 75 | <ShellContent Title="Wild" |
| 76 | ContentTemplate="{DataTemplate views:WildCatsPage}" /> |
| 77 | </Tab> |
| 78 | <Tab Title="Dogs" Icon="dogs.png"> |
| 79 | <ShellContent ContentTemplate="{DataTemplate views:DogsPage}" /> |
| 80 | </Tab> |
| 81 | </FlyoutItem> |
| 82 | |
| 83 | <TabBar> |
| 84 | <ShellContent Title="Home" Icon="home.png" |
| 85 | ContentTemplate="{DataTemplate views:HomePage}" /> |
| 86 | <ShellContent Title="Settings" Icon="settings.png" |
| 87 | ContentTemplate="{DataTemplate views:SettingsPage}" /> |
| 88 | </TabBar> |
| 89 | </Shell> |
| 90 | ``` |
| 91 | |
| 92 | ```csharp |
| 93 | // AppShell.xaml.cs |
| 94 | public partial class AppShell : Shell |
| 95 | { |
| 96 | public AppShell() |
| 97 | { |
| 98 | InitializeComponent(); |
| 99 | Routing.RegisterRoute("animaldetails", typeof(AnimalDetailsPage)); |
| 100 | Routing.RegisterRoute("editanimal", typeof(EditAnimalPage)); |
| 101 | } |
| 102 | } |
| 103 | ``` |
| 104 | |
| 105 | ## Workflow: Navigate with GoToAsync |
| 106 | |
| 107 | All programmatic navigation uses `Shell.Current.GoToAsync`. Always `await` the call. |
| 108 | |
| 109 | ### Route Prefixes |
| 110 | |
| 111 | | Prefix | Meaning |