BlueOceans1st
BlueOceans1st

Reputation: 94

Xamarin.Forms Shell GoToAsync is not working as expected in iOS

I am using the Xamarin.Forms - Shell feature. I need to navigate from one tab (root) to another tab (second level). The example has three pages, for simplicity I named Page1, Page2, and Page3. Page1 and Page2 are main tabs for the App Shell, the Page 3 is a second level of Page1 (stack).

The next code is part of AppShell.xaml:

  <FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
     <ShellContent Route="page1" Title="Page1" ContentTemplate="{DataTemplate local:Page1}" />
     <ShellContent Route="page2" Title="Page2" ContentTemplate="{DataTemplate local:Page2}" />
</FlyoutItem>

The constructor in AppShell.cs is

 public AppShell()
        {
            InitializeComponent();
            Routing.RegisterRoute(nameof(Page3), typeof(Page3));
        }

Page 1 and Page 3 are ver similar, just to represent two pages. The next is Page1.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="TestGoTo.Views.Page1"
              Title="Page1" BackgroundColor="LightGreen">
    <ContentPage.Content>
        <StackLayout>
            <Label Text="Welcome to Page1"
                VerticalOptions="CenterAndExpand" 
                HorizontalOptions="CenterAndExpand" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Page2.xaml includes a button to call the GoToAsync function

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="TestGoTo.Views.Page2"
             Title="Page2" BackgroundColor="LightYellow">
    <ContentPage.Content>
        <StackLayout>
            <Label Text="Page2" HorizontalOptions="CenterAndExpand" />
            <Button Text="GoTo" Clicked="Button_Clicked"></Button>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Page2.cs - Button Action is

private async void Button_Clicked(object sender, EventArgs e)
        {
             await Shell.Current.GoToAsync($"//page1/{nameof(Page3)}");
        }

The Problem:

When you go the Page2 and click the button, the expected behavior is to show the page 3 under tab of page 1, but you remain in the tab/page2. If you go (manually) to page 1 you will see the stack with the page 3. So, the page 3 is in the right place (loaded), but you did not see it because you remain in the page 2.

This problem is presented only in iOS, Android works as expected.

What's wrong here? Is there a Bug in Xamarin.Forms (Shell for iOS)?

Your help is appreciated.

Upvotes: 2

Views: 2558

Answers (2)

ToolmakerSteve
ToolmakerSteve

Reputation: 21321

I think it will work better if you declare the route, the way you want to use it. Here, you want page3 to be a sub-page of page1, but you don’t declare its route that way.

Try:

Routing.RegisterRoute("page1/page3", typeof(Page3));

Upvotes: 1

BlueOceans1st
BlueOceans1st

Reputation: 94

Looks like you cannot navigate to another stack (even if you name it) without changing the CurrentItem. For some reason Android accepted, but not iOS.

I just found a Workaround. I don't like too much, but now it is working. You need to change the CurrentItem (Shell.Current.CurrentItem) to a tab you want to navigate. In this case I want to navigate to the Tab1 (page1). so, I need to change it the CurrentItem as

  Shell.Current.CurrentItem = Shell.Current.CurrentItem.Items[0];

or I can use a better way (if I do not know the index).

Shell.Current.CurrentItem = Shell.Current.CurrentItem.Items.FirstOrDefault(x => x.Title= "Page1");

Below is the new button action.

  private async void Button_Clicked(object sender, EventArgs e)
        {
            
            Shell.Current.CurrentItem = Shell.Current.CurrentItem.Items.FirstOrDefault(x => x.Title=="Page1");
            //Shell.Current.CurrentItem = Shell.Current.CurrentItem.Items[0];
            await Shell.Current.GoToAsync($"//page1/{nameof(Page3)}");
        }

Comments are welcome. Thanks!

Upvotes: 1

Related Questions