我如何在使用 Prism 的视图模型中从我的应用程序 class 执行导航

How do i perform navigation from my App class while in a viewmodel with Prism

我目前正在开发一个应用程序,其中我们有一个名为 "tips" 的功能,它本质上是微博。在这些基于 html 的博客中,您可以通过普通的 hyperlinks link 访问我们应用程序中存在的其他 "Content"。

该应用程序设置为打开这些 link 的 url 方案,并且所有平台都有自己的代码,通过 MessagingCenter 将新的 uri 汇集到 xamarin 表单应用程序中,该消息中心具有应用内的订阅者 class 像这样:

 MessagingCenter.Subscribe(Current, DoshiMessages.NewUri, async (Application app, string uri) =>
 {
     var result = await HandleUriNavAsync(uri);

     if (!result)
        await Container.Resolve<IUserDialogs>().AlertAsync("Link was invalid");
 });

调用:

    private async Task<bool> HandleUriNavAsync(string uri)
    {
        if (uri == null)
            return false;

        await NavigationService.NavigateAsync(new Uri(uri, UriKind.Absolute));
        return true;
    }

现在这适用于绝对 uri,但如果我将其更改为

        //Example: uri = www.example.com/main/nav/test?userid=0
    private async Task<bool> HandleUriNavAsync(string uri)
    {
        if (uri == null)
            return false;

        //Example: relative = test?userid=0
        var relative = uri.Split('/').Last();
        await NavigationService.NavigateAsync(new Uri(relative, UriKind.Relative));
        return true;
    }

导航从不触发,但没有抛出异常并且任务成功完成(我已经检查过)。请注意,上面的代码是在应用程序已经 运行 并且已经具有活动视图模型时执行的。

是否有明显的错误,是否有更好的方法来实现这一点?

干杯!

我测试了你的代码,得到的结果如下图所示,这个问题与uri类型有关。

您已设置 UriKind.Absolute,因此您 uri 类型应为 www.example.com/main/nav/test?userid=0

如果设置UriKind.Relative,拆分uri后,可以设置这种类型的uri。

最后,在VS中没有抛出任何异常,这就是有线。

所以我最终找到了一个非常有效的解决方法。 这有点粗略,但因为我所有的视图模型都继承了一个共同的基础 class 我可以在 Prism PageUtils

的帮助下获取当前视图模型
MessagingCenter.Subscribe(Current, DoshiMessages.NewUri, async (Application app, string uri) =>
{
    try
    {
        var relative = uri.Split('/').LastOrDefault();

        if(relative != null)
        {
            var currentVM = PageUtilities.GetCurrentPage(MainPage).BindingContext as ViewModelBase;
            await currentVM.HandleNewUriAsync(relative);
        }
    }
    catch(Exception ex)
    {
       Crashes.TrackError(ex);
    }
});

然后只在当前视图模型中执行导航

    public async Task HandleNewUriAsync(string uri)
    {
        await _navigationService.NavigateAsync(new Uri(uri, UriKind.Relative));
    }