Xamarin Forms 中的 Prism 导航用法 App.OnAppLinkRequestReceived

Prism navigation usage from Xamarin Forms App.OnAppLinkRequestReceived

我正在构建一个使用某些应用程序 link 的应用程序。在下面的示例中,我想在用户从电子邮件激活 link 时打开一个 ResetPasswordPage。

protected override async void OnInitialized()
{
    InitializeComponent();
    await NavigationService.NavigateAsync("/NavigationPage/LoginPage");
}

protected override void OnAppLinkRequestReceived(Uri uri)
{
    if (uri.Host.EndsWith("site.nl", StringComparison.OrdinalIgnoreCase))
    {
        if (uri.AbsolutePath.StartsWith(@"/appname/resetpassword/"))
        {
            if (uri.Segments.Length == 4)
            {
                string resetCode = uri.Segments[3];

                NavigationParameters param = new();
                param.Add(NavConst.PasswordResetCode, resetCode);

                await NavigationService.NavigateAsync("ResetPasswordPage", param);
            }
        }
    }
}

此代码有效,但不是我所期望的(对于 iOS 和 Android)。我希望将 ResetPasswordPage 添加到在 OnInitialized 中设置的导航堆栈,以便它在导航栏中包含一个后退按钮,在这种情况下将用户带回登录页面。

但是,导航堆栈似乎被替换了。当显示 ResetPasswordPage 并且用户单击硬件后退按钮时,应用程序将关闭。但是,我希望它回到用户之前所在的位置。

我是否没有很好地理解某些导航概念,或者这可能是一个错误?

NavigationService 是 Prism 中针对 Xamarin.Forms 的一项相当独特的服务。它是为每个页面构建的新导航,导航堆栈取决于您从何处导航。

例如,当您从 MasterDetailPage / FlyoutPage 的上下文导航时,它会理解您并不是要在该页面顶部推送模式,而是从 Detail/Flyout 的上下文开始.如果 NavigationService 不断更新页面上下文,那么注入 MasterDetailPage/FlyoutPage 的 ViewModel 的导航服务将不知道它需要该页面作为导航的上下文。

您的问题最终是您从应用程序的上下文导航,该应用程序具有未设置页面的 NavigationService。因此,即使是相对导航仍将具有绝对导航的效果,从而重置 Application.MainPage,因为 NavigationService 不具有对另一个页面的上下文理解。

根据您的业务需求,您有几种不同的选择。一种是进行绝对导航,为您提供所需的导航堆栈。

您可能希望获取当前显示的页面并更新 NavigationService 以了解它。在应用程序 class 中,您可以添加如下内容:

protected override void OnAppLinkRequestReceived(Uri uri)
{
    if (NavigationService is IPageAware pa)
    {
        page.Page = PageUtilities.GetCurrentPage(MainPage);
    }

    if (someCondition)
    {
        // This will now navigate from relatively from the page
        // returned by GetCurrentPage.
        NavigationService.NavigateAsync("SomeRelativeUrl")
            .OnNavigationError(HandleNavigationError);
    }
}