如何为 Xamarin.Forms(视图)导航堆栈重置 Prism?

How to reset Prism for Xamarin.Forms (view) navigation stack?

当我尝试从我的应用程序发送电子邮件时,我正在解决 Prism.Forms (v6.2.0) 和 Xamarin 消息传递插件 (Xam.Plugins.Messaging v3.2.1) 之间的冲突。

以下代码 - 从我的一个 ViewModels 执行:

using Plugin.Messaging;

if (MessagingPlugin.EmailMessenger.CanSendEmail)
{
    var email = new EmailMessageBuilder()
        .To("test@testemail.com")
        .Subject("Email subject here!")
        .Body("Dear friend,\nI would like to say...\n\n\n")
        .Build();
    MessagingPlugin.EmailMessenger.SendEmail(email);
}

产生此错误 - 要发送的电子邮件永远不会显示在屏幕上:

Warning: Attempt to present <MFMailComposeViewController: 0x108fb4400> on <Xamarin_Forms_Platform_iOS_PageRenderer: 0x107de67c0> whose view is not in the window hierarchy!

我认为发生这种情况是因为消息插件的 iOS 特定部分有一个 .GetVisibleViewController() 方法,该方法查找具有可见视图的 UIViewController 以显示待发送电子邮件在发送;它正在寻找 iOS 不喜欢的视图控制器。

我想指出,我有几乎相同的代码(与上面显示的代码)运行 在不使用 Prism.Forms 的 MVVM 模式 Xamarin.Forms 应用程序中没有问题 [编辑:Brian L. 在下面指出这个问题可能不是由 Prism 引起的,我倾向于同意他的观点;它更有可能与两个应用程序之间 "navigation flow" 的微小差异有关,即使电子邮件 building/sending 代码相同]。当 MessagingPlugin.EmailMessenger.SendEmail(email); 行执行时,屏幕上会弹出一封电子邮件,其收件人、主题和正文如代码所示;以及发送或取消按钮。这在非 Prism Xamarin.Forms 应用程序中运行良好。

所以,我已经解决了这个问题,足以使 .SendEmail(email) 方法调用正常工作。我必须将我的 X.F 页面(即我的视图模型的视图)传递给 iOS 特定的项目代码以在其上调用 .CreateViewController()。我用这个新的 UIViewController 创建了一个 UIWindow 作为它的 RootViewController,然后使 window .MakeKeyAndVisible()。我已经调整了 Xam.Plugins.Messaging 的代码,让我传入一个 UIViewController 来使用。 .SendEmail(email) 方法调用发生后,我处理了新创建的 UIWindow;这样在邮件发送或取消后我就看不到了。

一切正常,我可以按预期使用 Messaging 插件的电子邮件发送功能。

我唯一剩下的问题是,在发送电子邮件后,对原始 ViewModel 的 navigationService 实例(即尝试发送电子邮件的 ViewModel,使用上面的代码)的导航调用全部失败。发送电子邮件后,我的 view/viewmodel 上的其他功能正常运行;但是调用 navigationService.GoBackAsync()navigationService.NavigateAsync() 失败并产生一个熟悉的错误:

Warning: Attempt to present <Xamarin_Forms_Platform_iOS_ModalWrapper: 0x1359c21a0> on <Xamarin_Forms_Platform_iOS_PlatformRenderer: 0x133df9640> whose view is not in the window hierarchy!

我相信我想要做的是重置我的 Prism NavigationService(视图)堆栈,使用类似这样的东西(Xamarin.Forms 的代码,没有 Prism):

Navigation.InsertPageBefore(new HomePage(), Navigation.NavigationStack.First());
Navigation.PopToRootAsync(true);

但我看不到像 Prism NavigationService 那样 "navigation stack altering operations" 的方法。但也许其他人会这样做?

提前致谢...

I have almost identical code (to that shown above) running without problems in an MVVM-patterned Xamarin.Forms app that does not use Prism.Forms

几乎相同,不完全相同。我想提一下,Prism 在 MVVM 方面没有做任何特别的事情。它只是为您设置 Page.BindingContext。而已。因此,如果您在没有 Prism 的应用程序中仅使用一个视图和一个 VM,那么使用 Prism 没有区别。

要回答您的问题,您只需使用绝对 URI 即可重置导航堆栈。

NavigateAsync("myapp:///NavigationPage/MainPage")

这相当于MainPage = new NavigationPage(new MainPage());