Xamarin Shell 引发 "Ambiguous Routes matched" 异常。

3
在Xamarin.Forms中,我在AppShell.xaml中使用以下路由声明:
 <FlyoutItem Title = "Toolbox"
             FlyoutDisplayOptions="AsMultipleItems"
             Route="Main">

      <ShellContent Title = "Toolbox"
                    ContentTemplate="{DataTemplate Views:Toolbox}"
                    Route="Toolbox"/>

 </FlyoutItem>

 <ShellContent Title = "Parameters"
               ContentTemplate="{DataTemplate Views:Parameters}"
               Route="Parameters"/>

AppShell.xaml.cs 中,我为 工具箱 页面添加了一个上下文页面导航。
public AppShell ()
{
    InitializeComponent ();

    Routing.RegisterRoute("Toolbox/TBOuvriers", typeof(TBOuvriers));

    BindingContext = this;
}

当我尝试从工具箱页面显示上下文页面导航时:
await Shell.Current.GoToAsync("//Main/Toolbox/TBOuvriers");
我遇到了这个异常:

System.ArgumentException: 匹配到模糊路由://Main/Toolbox/TBOuvriers,找到以下匹配项:
//Main/Toolbox/TBOuvriers/TBOuvriers,
//Main/IMPL_Toolbox/Toolbox/TBOuvriers
参数名称:uri

在调用之前,我可以看到Shell变量的这些值:
Shell.Current.CurrentItem:"Title = Toolbox,Route = Main"
Shell.Current.CurrentState.Location:" { //Main/Toolbox}"
这似乎是期望的。
如果我尝试使用此调用显示页面:
await Shell.Current.GoToAsync("TBOuvriers");
我还会收到异常:System.Exception:超时获取异常详情
那么问题出在哪里?
那些路线是从哪里来的?!?
为什么工具箱页面注册了2次?
欢迎提出任何想法!
最好的问候

在进一步查看网上的文章时,我发现人们主要会声明新页面(例如上下文页面)为全局页面,当它们不出现在 fyout 菜单中时。如果我这样做,它对我有效。将它们像 xamarin shell 文档中的现有页面子页面(如我的主题中所示)一样声明是否存在问题? - Belight
相同的观察点:在Xanimals演示项目中,他们使用 "Routing.RegisterRoute("monkeydetails", typeof(MonkeyDetailPage));" 而不是 "Routing.RegisterRoute("monkey/details", typeof(MonkeyDetailPage));"。 为什么?应该更容易从每个动物页面调用 "await Shell.Current.GoToAsync("details");" 而不是 *"await Shell.Current.GoToAsync($"{state.Location}/{destinationRoute}?name={animalName}");"*。 - Belight
你可以在你的项目中尝试这种方式,有任何问题吗? - Cherry Bu - MSFT
我做的与 XAnimals 相同。所有独立页面都在根目录中注册。但是,我无法成功应用官方文档中提供的方法。所以,对我来说可以工作但不是最佳方式,也许。 - Belight
如果您有更好的解决此问题的方法,请在此分享,谢谢。 - Cherry Bu - MSFT
2个回答

28

如果有人遇到了这个问题,并出现了以下错误信息;

System.ArgumentException:“匹配的模糊路线为:...”

这种情况会发生在您尝试在XAML(在appshell文件中)中注册路由,并且还尝试在C#代码后台中注册路由时。请只使用XAML或C#之一注册路由,不要同时注册。


1
我想补充一下,如果在两个地方都注册了,然后执行 await Shell.Current.GoToAsync("..");,应用程序会崩溃,并显示 System.NullReferenceException: 'Object reference not set to an instance of an object.' 的错误信息。 这也解决了问题。 - steven01804
这在实际中看起来怎么样呢?我在XAML中定义了一组Flyout项,但我已经在AppShell代码后台定义了路由。我需要在代码后台定义Flyout项吗?如果我只在XAML中注册路由,那么我将无法使用相对路由。 - AndrewJE
1
谢谢Damien,我花了几个小时思考我到底做错了什么哈哈。 - envyM6

1
如果由于某种原因你必须有两个注册,可以尝试以下方法:
<Tab Title="Groups">    
    <ShellContent Route="HomeTab"  ContentTemplate="{DataTemplate local:Home}" />
</Tab>

然后在代码中

 Routing.RegisterRoute("Home", typeof(Home)))

根据您的导航,您可能想尝试:

依赖于您的导航,您可能想尝试:

await Shell.Current.GoToAsync("//HomeTab", true);

或者

await Shell.Current.GoToAsync("//Home", true);

PS我讨厌AppShell导航

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接