How do I navigate from ShellContent/a ContentPage to a TabBar/TabbedPage in .NET MAUI Shell?

1.3k Views Asked by At

In my shell, I have defined a route "main". Nested underneath, I have defined a tabbar with the route "tabs". I want to navigate from my homepage to this tab page using a button. The tabpage should have a back button to get back to the homepage again (aka, I want to do relative navigation.).

When I try to do the navigation using this line of code: await Shell.Current.GoToAsync("tabs");

... I get this error: "System.ArgumentException: 'unable to figure out route for: tabs (Parameter 'uri')'"

Below is my AppShell.xaml:

<?xml version="1.0" encoding="UTF-8" ?>
<Shell
    x:Class="MauiTabShell.AppShell"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:MauiTabShell"
    xmlns:pages="clr-namespace:MauiTabShell.Pages"
    Shell.FlyoutBehavior="Disabled">
    <ShellContent
        Title="Home"
        ContentTemplate="{DataTemplate local:MainPage}"
        Route="main">
        <TabBar Route="tabs">
            <ShellContent ContentTemplate="{DataTemplate pages:PageOne}" />
            <ShellContent ContentTemplate="{DataTemplate pages:PageTwo}" />
            <ShellContent ContentTemplate="{DataTemplate pages:PageThree}" />
        </TabBar>
    </ShellContent>
</Shell>

Reproduction: https://github.com/BurkusCat/MauiShellTabNavRepro

  1. I have tried having the tabbar at the same level as the homepage and doing absolute navigation ("//tabs") which works, but doesn't give me a back button
  2. I have tried registering a TabbedPage in "AppShell.xaml.cs`, but TabbedPages don't work with Shell according to Maui documentation
Routing.RegisterRoute("tabs", typeof(MyTabbedPage));
  1. I've tried creating a "TabBar" xaml and xaml.cs file in a similar way to the way you would create a ContentPage or TabbedPage. This didn't work. I tried doing this in pure CSharp too.
  2. I've tried various routes such as ("//home/tabs") to get the navigation to work but no joy.

I feel like this should be the most simple task but I have had no success so far and have not been able to find any good examples of this kind of navigation (the documentation and most tutorials start on a tabbar/flyout rather than trying to navigate from a homepage to a page with tabs).

Ultimately, my goal is to navigate from a ContentPage to a page with tabs. So I don't particularly care if that ends up being a TabBar or a tab page. I think I could probably skip shell for this one navigation, but then I'd lose all the dependency injection / parameter passing which would be bad.

2

There are 2 best solutions below

0
On

You can follow the solution of @H.A.H. ... And for the back button problem, you can solve it by overriding OnBackButtonPressed

protected override bool OnBackButtonPressed()
{
  BackHomeAsync();
  return true; //this blocks the app from Closing 
}

private async Task BackHomeAsync()
{
  await Shell.Current.GoToAsync($"//{nameof(MainPage)}");
}

I hope this might help u.

6
On

Your shell is incorrect.

https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/shell/#app-visual-hierarchy

Not the navigation, the structure itself.

The correct way to implement TabBar is here: https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/shell/tabs

Short answer is:

<TabBar>
   <Tab>
      <ShellContent>

Not:

<ShellContent>
  <TabBar>
    <ShellContent>

Edit: The structure you requested:

<ShellItem Route="HomePage">
    <ShellContent ContentTemplate="{DataTemplate view:HomePage}"/>
</ShellItem>

<TabBar>
        <Tab Route="PageOne">
          <ShellContent ContentTemplate="{DataTemplate view:PageOne}"/>
        </Tab>
        <Tab Route="PageTwo">
          <ShellContent ContentTemplate="{DataTemplate view:PageTwo}"/>
        </Tab>
</TabBar>

You can switch between them with "//HomePage" and "//PageOne".