0
votes

I am trying to figure out how to navigate through my shell pages from a button click event on the individual pages. I want the button click to be the same as if opening the menu and selecting the next page. For example I will have a series of pages where I gather information from a user to build a report. I want the user to input some data on the first page and click next to go the the 2nd page to enter more information and so on. my reason for wanting to keep the shell page menu is so that if a user decides they need to go back to a page to modify some information previously entered, they can open the shell menu and choose the page as opposed to clicking the back button n times to return to a previous page.

I have tried using routing and Shell.Current.GoToAsync() to achieve this but get a null reference in Main.cs at line UIApplication.Main(args, null, "AppDelegate");I am avoiding using Navigation.PushModalAsync(new Page2()); because navigating in this manner removes the hamburger menu to my shell page. I have also tried making a function in ShellPage.xaml.cs called Change_Page() which I call via the button click on page one. in this function i have tried the same Shell.Current.GoToAsync("myPage2") which resulted in the null reference error again as well as trying Shell.Current.CurrentItem = myPage2; which resulted in a break at the same line but insstead ogf an error I got some UIKit.UIApllication issue that didn't seem to display an error but did stop the debugger here.

ShellPage.xaml

...
<FlyoutItem Title="Page1">
    <ShellContent>
        <views:Page1View Title="Page1" x:Name="myPage1" Route="myPage1"/>
    </ShellContent>
</FlyoutItem>
<FlyoutItem Title="Page2">
    <ShellContent>
        <views:Page2View Title="Page2" x:Name="myPage2" Route="myPage2"/>
    </ShellContent>
</FlyoutItem>
<FlyoutItem Title="Page3">
    <ShellContent>
        <views:Page1View Title="Page1" x:Name="myPage3" Route="myPage3"/>
    </ShellContent>
</FlyoutItem>
...

myShellPage.xaml.cs

[DesignTimeVisible(false)]
    public partial class MyShellPage : Shell
    {
        public MyShellPage()
        {
            InitializeComponent();

            Routing.RegisterRoute("myPage1", typeof(CallInfoPage));
            Routing.RegisterRoute("myPage2", typeof(SpillInfoPage));
            Routing.RegisterRoute("myPage3", typeof(ItemsPage));

            Device.StartTimer(TimeSpan.FromSeconds(3), () =>
            {
                // Do something
                Current.CurrentItem = myPage3; // throws error 'myPage3' does not exist in current context
                return false; // True = Repeat again, False = Stop the timer
            });
        }
    }

Page1View.xaml

...
<Button Text="Next" Clicked="Next_Clicked" />
...

Page1View.xaml.cs

...
async void Next_Clicked(System.Object sender, System.EventArgs e)
    {
        await Shell.Current.GoToAsync("myPage2");
    }
...
1

1 Answers

0
votes

You also need to Register page routes when running .

In the Shell subclass constructor, or any other location that runs before a route is invoked, additional routes can be explicitly registered for any pages that aren't represented in the Shell visual hierarchy:

Routing.RegisterRoute("pageone", typeof(ItemsPage));
Routing.RegisterRoute("pagetwo", typeof(AboutPage));

These pages can then be navigated to using URI-based navigation, from anywhere within the application. The routes for such pages are known as global routes.

async void NavigateThird_Clicked(object sender, EventArgs e)
{
    await Shell.Current.GoToAsync("pagetwo");
}

It works.

enter image description here

About AppShell can not invoke Shell.Current.GoToAsync("myPage2") or Shell.Current.CurrentItem = myPage2 in Constructor method . In addition , you want to show hamburger menu , you will see Current.GoToAsync can not do that . Here you need to use Current.CurrentItem to implement that . I have a workaround by using Timer to invoke them delay for a while .

public AppShell()
{
    InitializeComponent();

    Routing.RegisterRoute("pageone", typeof(ItemsPage));
    Routing.RegisterRoute("pagetwo", typeof(AboutPage));
    Routing.RegisterRoute("pagethird", typeof(PageThird));

    Device.StartTimer(TimeSpan.FromSeconds(3), () =>
    {
        // Do something
        Current.CurrentItem = pagethird;
        return false; // True = Repeat again, False = Stop the timer
    });
}

Xaml code :

<FlyoutItem Title="main"
            FlyoutDisplayOptions="AsMultipleItems">
    <ShellContent x:Name="pageone" Title="Page1" FlyoutIcon="icon.png" ContentTemplate="{DataTemplate local:ItemsPage}" Route="pageone" />
    <ShellContent x:Name="pagetwo" Title="Page2"
                    FlyoutIcon="icon.png"
                    ContentTemplate="{DataTemplate local:AboutPage}" Route="pagetwo" />
</FlyoutItem>
<FlyoutItem Title="Two" x:Name="pagethird">
    <ShellContent  Title="Page3"
                    FlyoutIcon="icon.png"
                    ContentTemplate="{DataTemplate local:PageThird}"
                    Route="pagethird" />
</FlyoutItem>

The effect :

enter image description here