如何在顶部导航中没有后退按钮的情况下在 Xamarin Shell 中切换页面

How to switch pages in the Xamarin Shell without a back button in the top navigation

我的左侧菜单导航中有选择器 shell 可以更改主页语言,
例如实际上是英文的应用程序。当我更改为法语时,它会更改并重定向到带有法语文本的主页。
问题是当我在导航页面中按下后退箭头时,它返回到旧语言(英语)。

这里是shell导航

<Shell ..>
    <Shell.FlyoutHeader>
<Picker  ItemsSource="{Binding MultiLang, Mode=TwoWay}" SelectedItem="{Binding SelectedLang}">
     </Picker>
</Shell.FlyoutHeader>


<ShellContent x:Name="home"
Route="main"
ContentTemplate="{DataTemplate home:Dashboard}" />
</Shell>

这是重定向到主页的方法:

private async void ChangeLange(string lang)
{
...
            Routing.RegisterRoute(nameof(Dashboard), typeof(Dashboard));
            await Shell.Current.GoToAsync($"{nameof(Dashboard)}");// it redirect but with button back
            RemoveStackNavigation ()
         //   await Shell.Current.GoToAsync("//main"); like this , it dosent refresh the page with 

            Shell.Current.FlyoutIsPresented = false; 
}

这里是 MVMM

        public string _selectedLang;
        public string  SelectedLang
        {
            get
            {
                return _selectedLang;
            }
            set
            {
                if (_selectedLang != value)
                {
                    _selectedLang = value;
                    OnPropertyChanged("SelectedLang");
                    ChangeBuilding(value);

                }
            }
        }

我试过 RemoveStackNavigation,然后像这样重定向到仪表板:

        public static void RemoveStackNavigation()
        {
            var existingPages = Shell.Current.Navigation.NavigationStack.ToList();
            foreach (var page in existingPages)
            {
                if (page != null)
                    Shell.Current.Navigation.RemovePage(page);
            }
        }

Shell 的导航堆栈有些特别。清除导航堆栈不是一个好的选择。我们总是使用 Routes 为 Shell 做导航。您需要知道哪个会生成堆栈。

  • 路由,它定义作为 Shell 视觉层次结构的一部分存在的内容的路径。
  • 一页。 Shell 视觉层次结构中不存在的页面可以从 Shell 应用程序中的任何位置推送到导航堆栈。例如,详细信息页面不会在 Shell 视觉层次结构中定义,但可以根据需要推送到导航堆栈上。

更多详细信息,请查看 MS 文档。 https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/navigation

当你按下后退按钮时,覆盖后退按钮事件,然后判断路线做导航会更好。使用具体的路由名称返回

更新:

我们在 Xamarin Forms 中调用的导航栏编译后,在运行时变成 Android 的操作栏。

在LoadApplication(new App())之后设置工具栏;在 MainActivity 的 OnCreate 中。

        AndroidX.AppCompat.Widget.Toolbar toolbar
     = this.FindViewById<AndroidX.AppCompat.Widget.Toolbar>(Resource.Id.toolbar);
    SetSupportActionBar(toolbar);

然后覆盖 OnOptionsItemSelected()。当您按下导航栏上的后退按钮时,将触发此事件。

 public override bool OnOptionsItemSelected(IMenuItem item)
    {
   
     }

我不太了解发生了什么,但我假设您想在滑动选择器时更改应用程序的语言。我认为问题不在于导航,而是页面的创建方式。

例如,如果您 运行 现在您的应用程序转到 Main page 它将存储在临时缓存中,因此如果您转到另一个页面并返回,它将加载比您第一次在应用程序中输入更快。

您可以测试的内容是(仅测试):

  • 将此选择器结果(例如:如果是法语,则变量为 1,如果是英语,则为 2,等等)并将此变量作为 static,只是为了它不要刷新,你丢失了这个值。
  • 在您的主页中,创建一个 Label 并设置动态文本:
switch(pickerResult):
case "1":
 lblTest.Text = "french";
break;
case "2":
 lblTest.Text = "English";
break;
case "3":
 lblTest.Text = "Italian";
break;

并且,当您点击后退按钮时转到的页面现在以英文显示,创建与上面完全相同的标签,然后查看是否有效。

如果有效,那么一些提示:

  • 您的页面可以包含静态文本;
  • 您的页面无法在 运行 时间内获取语言;

所以,要解决这个问题,您需要创建一些 List<Words> 并在更改选择器时获取正确的语言:

private void SelectedIndexChanged(sender s, EventArgs e)
{
  switch(pickerResult):
  case "1":
     App.wordsList = GetListOfWords("french");
  break;
}

这个 GetListOfWords 是一个函数,你可以调用你的 xml 或应用程序资源或任何你用来改变语言的东西(即使是翻译)。

现在您的 wordsList(或您如何称呼它)将被更新。