C# 将xamarin.forms.shell重置为“返回”按钮上的初始页面

C# 将xamarin.forms.shell重置为“返回”按钮上的初始页面,c#,xaml,xamarin.forms,C#,Xaml,Xamarin.forms,非常简短的版本是 我想,在代码中,让shell回到它最初在appstart上显示时的位置,以及它的外观 我有一个xamarin.forms.shell页面,其中显示了许多使用弹出式按钮和选项卡的内容页面。 最初加载shell时,它会显示第一个弹出式项目内容页面,这是我的“主要活动/页面”,具有最常见的UI 如果我转到另一个弹出式项目内容页面,我希望backbutton导航到“主弹出式按钮”,并且只有在单击此“主弹出式按钮”上的back按钮时,它才会离开应用程序 虽然我可以截取backbutton

非常简短的版本是 我想,在代码中,让shell回到它最初在appstart上显示时的位置,以及它的外观

我有一个xamarin.forms.shell页面,其中显示了许多使用弹出式按钮和选项卡的内容页面。 最初加载shell时,它会显示第一个弹出式项目内容页面,这是我的“主要活动/页面”,具有最常见的UI

如果我转到另一个弹出式项目内容页面,我希望backbutton导航到“主弹出式按钮”,并且只有在单击此“主弹出式按钮”上的back按钮时,它才会离开应用程序

虽然我可以截取backbutton并导航到其他页面,但它没有单击“主页”弹出按钮的效果。如果我这样做

Shell.Current.GoToAsync(name of route to my main flyout);
我确实进入了主页,但随着全屏和弹出式菜单的出现,工具栏和选项卡都消失了

如果我转到另一个弹出式项目内容页面,我希望backbutton导航到“主弹出式按钮”,并且只有在单击此“主弹出式按钮”上的back按钮时,它才会离开应用程序

您可以在每个页面显示时存储页面标志类型,以确定它是否为主页面。页面标志类型只需定义两种类型:一种是
0
(表示主页),另一种是
1
(其他页面)。然后,当按下物理后退按钮时,您可以确定是否需要显示退出消息以退出应用程序

例如,使用在每页的
显示方法中存储标志:

主页:

public partial class MainPage: ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();
        Preferences.Set("PageType", "0");
    }
}
其他页面:

public partial class OtherPage : ContentPage
{
    public OtherPage()
    {
        InitializeComponent();
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();
        Preferences.Set("PageType", "1");
    }
}
然后,当点击后退按钮时,我们可以确定我们需要做什么

private async void Button_Clicked(object sender, EventArgs e)
{
    var pageType = Preferences.Get("PageType", "0");
    if (pageType == "0")
    {
        // Exit application method
        ExitApplication();
    }
    else
    {
        // back to the Main Page
        await Shell.Current.GoToAsync($"//MainRoute/MainPage");
    }
}
以下是
Xaml
代码的弹出项

<FlyoutItem Route="MainRoute"
            Title="Animals"
            FlyoutDisplayOptions="AsMultipleItems">
    <Tab Title="MainPage"
         Route="MainPage"
         Icon="paw.png">
        <ShellContent Route="cats"
                      Style="{StaticResource DomesticShell}"
                      Title="Cats"
                      Icon="cat.png"
                      ContentTemplate="{DataTemplate views:CatsPage}" />
        <ShellContent Route="dogs"
                      Style="{StaticResource DomesticShell}"
                      Title="Dogs"
                      Icon="dog.png"
                      ContentTemplate="{DataTemplate views:DogsPage}" />
    </Tab>

    <ShellContent Route="PageTwo"
                  Style="{StaticResource MonkeysShell}"
                  Title="Monkeys"
                  Icon="monkey.png"
                  ContentTemplate="{DataTemplate views:MonkeysPage}" />
    <ShellContent Route="PageThree"
                  Style="{StaticResource ElephantsShell}"
                  Title="Elephants"
                  Icon="elephant.png"
                  ContentTemplate="{DataTemplate views:ElephantsPage}" />
    <ShellContent Route="PageFour"
                  Style="{StaticResource BearsShell}"
                  Title="Bears"
                  Icon="bear.png"
                  ContentTemplate="{DataTemplate views:BearsPage}" />
</FlyoutItem>

为此,您需要在所需的内容页中通过定义一个命令来覆盖,该命令将在用户按下该页中的“后退”按钮时触发,然后通过其定义的根导航到您的根页面:

CatsPage.Xaml

<Shell.BackButtonBehavior>
   <BackButtonBehavior Command="{Binding BackCommand}"/>
</Shell.BackButtonBehavior>
public ICommand BackCommand { get; private set; }

public CatsPage()  //or VM constructor
{
    ...
BackCommand = new Command(async (x) => await Shell.Current.GoToAsync("///MainRoute"));
}
public CatsPage() //or VM constructor
{
    ...
    BackCommand = new Command(async (x) => {
    if (Shell.Current.CurrentState.Location.ToString().Equals("//MainRoute/MainPage/Cats"))
      //popup to quit
else if (Shell.Current.CurrentState.Location.ToString().Equals("//MainRoute/Cats"))
        await Shell.Current.GoToAsync("///MainRoute");
    // or use to go back to previous: await Shell.Current.GoToAsync("..");
   });
}
如果您将此内容页用作多个
弹出项
中的
选项卡
内容,但您只希望此行为适用于位于第一个
弹出项
中的
内容页
,则可以基于页面绝对路径或
标题
属性添加条件测试:

来自jiang的Xaml示例回答:

<FlyoutItem Route="MainRoute"
            Title="Animals"
            FlyoutDisplayOptions="AsMultipleItems">
    <Tab Title="MainPage"
         Route="MainPage"
         Icon="paw.png">
        <ShellContent Route="cats"
                      Style="{StaticResource DomesticShell}"
                      Title="Cats"
                      Icon="cat.png"
                      ContentTemplate="{DataTemplate views:CatsPage}" />
        <ShellContent Route="dogs"
                      Style="{StaticResource DomesticShell}"
                      Title="Dogs"
                      Icon="dog.png"
                      ContentTemplate="{DataTemplate views:DogsPage}" />
    </Tab>

    <ShellContent Route="PageTwo"
                  Style="{StaticResource MonkeysShell}"
                  Title="Monkeys"
                  Icon="monkey.png"
                  ContentTemplate="{DataTemplate views:MonkeysPage}" />

    <ShellContent Route="cats"
                  Style="{StaticResource DomesticShell}"
                  Title="Cats2"
                  Icon="cat.png"
                  ContentTemplate="{DataTemplate views:CatsPage}" />
</FlyoutItem>


再次,您需要正确定义并使用
选项卡和
弹出项
路由层次结构,否则它将导致异常

是否单击了
按钮()
页面中定义的用户自定义按钮的事件处理程序?@Cfun,但您也可以在本机平台中定义它来调用物理后退按钮。您(您和Junior Jiang)都给了我所需的线索,那就是不要跳转到一个按类指向特定页面的路由,而是跳转到一个指向弹出项的路由。很明显,现在我想起来了,但那就是我错的地方。我本想将两者都标记为答案,但不得不选择,在它还显示Shell.Current.CurrentState.Location之前,我选择了这个选项,这是一个简单的解决方案,可以查看后面应该调用什么行为。