Dudu
Dudu

Reputation: 65

Xamarin.Forms Shell navigation outside the visual hierarchy

I'm having a problem with how to implement navigation to pages that are not represented in shell visual hierarchy (defined in my Shell xaml).

From what I read about Shell navigation in the docs, there are two ways I can navigate to such a page:

  1. Using the Navigation property:
    Navigation.PushAsync(new TargetPage());
    
  2. Registering a route and using Shell's URI navigation:
    Routing.RegisterRoute("targetPageRoute", typeof(TargetPage));
    
    Shell.Current.GoToAsync("targetPageRoute");
    

Both methods encounter the same problem: Once you use either method to navigate to a page outside the visual hierarchy, normal navigation between Shell's flyoutItems (using the flyout menu) will crash the app with the error:

System.Collections.Generic.KeyNotFoundException: The given key 'MyProject.TargetPage' was not present in the dictionary.

How to reproduce:

  1. Add two items to Shell's visual hierarchy:

    <FlyoutItem Title="page 1">
        <Tab>
            <ShellContent>
                <local:Page1 />
            </ShellContent>
        </Tab>
    </FlyoutItem>
    
    <FlyoutItem Title="page 2">
        <Tab>
            <ShellContent>
                <local:Page2 />
            </ShellContent>
        </Tab>
    </FlyoutItem>
    
  2. Use a button on Page1 to navigate to Page3 (a page not defined above) using either of the two ways to navigate described at the top of this post:
    private void Button_Clicked(object sender, EventArgs e) {
        Navigation.PushAsync(new Page3());
    }
    
  3. Use the flyout menu to navigate to Page2
  4. Use the flyout menu to navigate to Page1 - the app should now crash.

I have tested this in my main project and in a small test project extensively and cant seem to find a solution. Any help would be greatly appreciated.

Upvotes: 1

Views: 3548

Answers (3)

SnowCore
SnowCore

Reputation: 38

Here's the same issue from xamarin forms' github: https://github.com/xamarin/Xamarin.Forms/issues/6738 Also, if you scroll down, you'll see pull request, which actually resolves the problem (already helped our company's application). You have to implement a custom renderer, which is going to inherit from ShellItemRenderer, and override the existing HandleFragmentUpdate (because of the fact, that it uses private fields from the original ShellItemRendererBase, you'll have to rebase them here too (not override, just copy them from current xamarin android ShellItemRendererBase.cs file)). BUT, as the official docs suggest, you shall not just assign this renderer to a ShellItem derivative, instead, you'll have to create custom ShellRenderer with overriding it's CreateShellItemRenderer method (so it would create your fixed shell item renderer instead of the default one). You just apply this renderer to a custom shell control in xamarin forms.

Of course, everything you do now is temporary, until xamarin pushes new update with this fix included...

Upvotes: 1

Nicolai
Nicolai

Reputation: 21

Have you tried to add your Route before setting the BindingContext ? For Example :

public NavigationShell()
{
   Routing.RegisterRoute("targetPageRoute", typeof(TargetPage));
   BindingContext = this;
}

Upvotes: 0

Leo Zhu
Leo Zhu

Reputation: 14956

you could try to change the shell.xaml like this:

<FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
    <Tab Title="page 1">
        <ShellContent  >
            <local:Page1 />
        </ShellContent>
    </Tab>
    <Tab Title="page 2">
        <ShellContent   >
            <local:Page2 />
        </ShellContent>
    </Tab>
</FlyoutItem>

Upvotes: 0

Related Questions