Xamarin.forms 在使用Prism的viewmodel中,如何从应用程序类执行导航

Xamarin.forms 在使用Prism的viewmodel中,如何从应用程序类执行导航,xamarin.forms,xamarin.android,navigation,uri,prism,Xamarin.forms,Xamarin.android,Navigation,Uri,Prism,我目前正在开发一个应用程序,其中有一个叫做“提示”的功能,基本上就是微博。在这些基于html的博客中,您可以通过普通超链接链接到我们应用程序中存在的其他“内容” 该应用程序设置为打开这些链接的url方案,所有平台都有自己的代码,通过MessagingCenter将新uri导入xamarin表单应用程序,MessagingCenter在应用程序类中有一个子用户,如下所示: MessagingCenter.Subscribe(Current, DoshiMessages.NewUri, async

我目前正在开发一个应用程序,其中有一个叫做“提示”的功能,基本上就是微博。在这些基于html的博客中,您可以通过普通超链接链接到我们应用程序中存在的其他“内容”

该应用程序设置为打开这些链接的url方案,所有平台都有自己的代码,通过MessagingCenter将新uri导入xamarin表单应用程序,MessagingCenter在应用程序类中有一个子用户,如下所示:

 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");
 });
MessagingCenter.Subscribe(当前,DoshiMessages.NewUri,异步(应用程序应用程序,字符串uri)=>
{
var result=await HandleUriNavAsync(uri);
如果(!结果)
wait Container.Resolve().AlertAsync(“链接无效”);
});
这要求:

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

        await NavigationService.NavigateAsync(new Uri(uri, UriKind.Absolute));
        return true;
    }
专用异步任务HandleUriNavAsync(字符串uri)
{
if(uri==null)
返回false;
等待NavigationService.NavigateAsync(新Uri(Uri,UriKind.Absolute));
返回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=www.Example.com/main/nav/test?userid=0
私有异步任务HandleUriNavAsync(字符串uri)
{
if(uri==null)
返回false;
//示例:relative=test?userid=0
var relative=uri.Split('/').Last();
等待NavigationService.NavigateAsync(新Uri(relative,UriKind.relative));
返回true;
}
导航从不触发,但不会引发异常,并且任务成功完成(我已检查)。注意:上面的代码是在应用程序已经运行并且已经有活动的viewmodels时执行的

有没有什么明显的我做错了,有没有更好的方法来实现这一点


干杯

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

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

如果设置了
UriKind.Relative
,则在分割uri之后,可以设置这种类型的uri

最后,在VS中没有抛出异常,这是非常有关联的。

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

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

如果设置了
UriKind.Relative
,则在分割uri之后,可以设置这种类型的uri

最后,在VS中没有抛出异常,这是非常有关联的。
因此,我最终找到了一个非常有效的解决方法。 这有点粗略,但因为我所有的viewmodels都继承了一个公共基类 我可以在Prism PageUtils的帮助下获得当前的viewmodel

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);
    }
});
然后在当前viewmodel中执行导航

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

所以我最终找到了一个很好的解决办法。 这有点粗略,但因为我所有的viewmodels都继承了一个公共基类 我可以在Prism PageUtils的帮助下获得当前的viewmodel

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);
    }
});
然后在当前viewmodel中执行导航

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

嗨,谢谢你的回答。糟糕的是,我忘了将UriKind更改为Relative,在上一个示例中,它是相对的。我已经编辑了我的问题。嗨,谢谢你的回答。糟糕的是,我忘了将UriKind更改为Relative,在上一个示例中,它是相对的。我已经编辑了我的问题。一些更详细的问题。。。1.您是如何在HandleUriNavAsync中获得NavigationService实例的?2.此导航触发器可以在应用程序中的任何位置执行吗?因此,无论您当前在哪个屏幕上(换句话说,无论当前的导航路径是什么?@depchie),NavigationService都是PrismApplication类的一个属性,我的应用程序类基于PrismApplication类。HandleUriNavAsync是我的应用程序类中的一个方法。使用绝对Uri的导航似乎在任何地方都能工作,但我只从当前活动的viewmoddelIn general中获得了相对Uri。您需要使用在VM中已ioc’ed的Uri,因为PRISM会跟踪其他内容以获得正确的结果navigation@Depechie我知道如果我从我的容器中解析一个新实例应用程序类,它会工作。比我的q的第二部分是重要的,不是所有的导航将立即工作。取决于模型页面是否打开以及其他内容。一般来说,对于PRISM,如果您想更新完整的导航堆栈,URL应该以一些更详细的问题开始。。。1.您是如何在HandleUriNavAsync中获得NavigationService实例的?2.此导航触发器可以在应用程序中的任何位置执行吗?因此,无论您当前在哪个屏幕上(换句话说,无论当前的导航路径是什么?@depchie),NavigationService都是PrismApplication类的一个属性,我的应用程序类基于PrismApplication类。HandleUriNavAsync是我的应用程序类中的一个方法。使用绝对Uri的导航似乎在任何地方都能工作,但我只从当前活动的viewmoddelIn general中获得了相对Uri。您需要使用在VM中已ioc’ed的Uri,因为PRISM会跟踪其他内容以获得正确的结果navigation@Depechie我知道如果我从我的容器中解析一个新实例应用程序类,它会工作。比我的q的第二部分是重要的,不是所有的导航将立即工作。取决于模型页面是否打开以及其他内容。一般来说,对于PRISM,如果要更新完整的导航堆栈,URL应以/