【问题标题】:Xamarin.Forms Shell navigation outside the visual hierarchy视觉层次结构外的 Xamarin.Forms Shell 导航
【发布时间】:2019-11-11 09:37:28
【问题描述】:

我在如何实现导航到未在 shell 视觉层次结构中表示的页面(在我的 Shell xaml 中定义)时遇到问题。

根据我读到的关于 Shell 导航in the docs 的内容,我可以通过两种方式导航到这样的页面:

  1. 使用导航属性:
    Navigation.PushAsync(new TargetPage());
    
  2. 注册路由并使用 Shell 的 URI 导航:
    Routing.RegisterRoute("targetPageRoute", typeof(TargetPage));
    
    Shell.Current.GoToAsync("targetPageRoute");
    

两种方法都遇到相同的问题:一旦您使用任何一种方法导航到视觉层次结构之外的页面,Shell 的 flyoutItems 之间的正常导航(使用弹出菜单)将使应用程序崩溃并出现错误:

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

如何重现:

  1. 向 Shell 的视觉层次结构添加两项:

    <FlyoutItem Title="page 1">
        <Tab>
            <ShellContent>
                <local:Page1 />
            </ShellContent>
        </Tab>
    </FlyoutItem>
    
    <FlyoutItem Title="page 2">
        <Tab>
            <ShellContent>
                <local:Page2 />
            </ShellContent>
        </Tab>
    </FlyoutItem>
    
  2. 使用本文顶部描述的两种导航方式之一,使用 Page1 上的按钮导航到 Page3(上面未定义的页面):
    private void Button_Clicked(object sender, EventArgs e) {
        Navigation.PushAsync(new Page3());
    }
    
  3. 使用弹出菜单导航到第 2 页
  4. 使用弹出菜单导航到第 1 页 - 应用现在应该崩溃了。

我在我的主项目和一个小型测试项目中对此进行了广泛测试,但似乎找不到解决方案。任何帮助将不胜感激。

【问题讨论】:

    标签: c# android xaml xamarin.forms xamarin.forms.shell


    【解决方案1】:

    这是来自 xamarin forms' github 的相同问题:https://github.com/xamarin/Xamarin.Forms/issues/6738 另外,如果你向下滚动,你会看到 pull request,它实际上解决了问题(已经帮助我们公司的应用程序)。 您必须实现一个自定义渲染器,该渲染器将从 ShellItemRenderer 继承,并覆盖现有的 HandleFragmentUpdate(因为它使用原始 ShellItemRendererBase 中的私有字段,您也必须在此处重新设置它们(而不是覆盖,只需从当前 xamarin android ShellItemRendererBase.cs 文件中复制它们))。 但是,正如官方文档所建议的那样,您不应只将此渲染器分配给 ShellItem 派生类,而是必须创建自定义 ShellRenderer 并覆盖它的 CreateShellItemRenderer 方法(因此它将创建您的固定外壳项目渲染器而不是默认的渲染器)。您只需将此渲染器应用于 xamarin 表单中的自定义 shell 控件。

    当然,您现在所做的一切都是暂时的,直到 xamarin 推送包含此修复程序的新更新...

    【讨论】:

      【解决方案2】:

      您可以尝试像这样更改 shell.xaml:

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

      【讨论】:

      • 您好,我已经测试了您的建议,应用程序不再崩溃。但是,使用此解决方案意味着整个应用程序都包含在单个弹出项中,这可能是一个优化问题吗?该应用程序还无法访问底部标签,这很遗憾。
      • 你需要什么效果?你可以给我一些草图吗?
      • 如果不想显示底部标签,可以设置Shell.TabBarIsVisible="False"
      • 我现在放弃了尝试在 shell 层次结构之外导航,只是将我的所有页面添加到 shell 中的某个位置,隐藏了选项卡。尽管如此,我描述的问题似乎是一个非常严重的错误,而您的回答只是一个没有问题的解决方法。
      • 我是否应该将此答案标记为已接受,因为它确实可以解决崩溃问题?如果出现更好的情况,我可以稍后标记不同的答案吗?我是新来的,对不起。 :)
      【解决方案3】:

      您是否尝试在设置 BindingContext 之前添加您的路线? 例如:

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

      【讨论】:

      • 我不确定我是否遵循您的解决方案。我正在描述的应用程序是一个简单的应用程序,有 3 个空白页面和一个按钮。我为什么要设置 BindingContext?
      猜你喜欢
      • 1970-01-01
      • 2020-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-18
      • 1970-01-01
      • 1970-01-01
      • 2010-10-03
      相关资源
      最近更新 更多