【问题标题】:How to reset Prism for Xamarin.Forms (view) navigation stack?如何为 Xamarin.Forms(视图)导航堆栈重置 Prism?
【发布时间】:2017-03-09 12:06:56
【问题描述】:

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

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

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);
}

产生此错误 - 待发送的电子邮件永远不会出现在屏幕上:

警告:尝试在 上显示 ,其视图不在窗口层次结构中!

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

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

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

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

我唯一剩下的问题是,在发送电子邮件后,对原始 ViewModel 的 navigationService 实例(即尝试发送电子邮件的 ViewModel,使用上面的代码)的导航调用都失败了。发送电子邮件后,我的视图/视图模型上的其他功能可以正常工作;但是调用navigationService.GoBackAsync()navigationService.NavigateAsync() 失败并产生一个熟悉的错误:

警告:尝试在 上呈现 ,其视图不在窗口层次结构中!

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

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

但我看不到像使用 Prism NavigationService 那样执行“导航堆栈更改操作”的方法。但也许其他人会这样做?

提前谢谢...

【问题讨论】:

    标签: navigation stack xamarin.forms prism reset


    【解决方案1】:

    我在不使用 Prism.Forms 的 MVVM 模式 Xamarin.Forms 应用程序中运行几乎相同的代码(如上所示)

    几乎相同,并不相同。我想提一下,Prism 对于 MVVM 并没有什么特别之处。它只是为您设置 Page.BindingContext。而已。因此,如果您在没有 Prism 的应用程序中仅使用 View 和 VM,则使用 Prism 没有区别。

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

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

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

    【讨论】:

    • 谢谢布赖恩,会试试看的!
    • 再次感谢布赖恩。这解决了我的问题。我现在没有打电话给navigationService.NavigateAsync("HomePage"),而是打电话给navigationService.NavigateAsync("app:///HomePage")——一切正常。我查找了有关 Prism Absolute URIs 的文档,我不清楚上面示例中的“myapp”是否是“魔术字符串”——或者需要为我的应用程序定制。但它似乎可以是“anystring:///HomePage”并且仍然有效。让我知道这是否是错误的。如果这有助于这个问题/回答的未来读者......
    • 没错。本质上,您只需要提供一个有效的绝对 URI。可以是从http://www.myapp.com/MainPage 到创建实际的new Uri("some uri", UriKind.Abslute)
    • @BrianLagunas 感谢您提供解决方案并解释其工作原理。我还有另外两个疑问,比如假设我从页面 A 导航到 B 到 C 到 D,然后在 D 中进行某些操作,如果我只需要删除页面 C,我该怎么做?如果我想处理 android 设备的后退按钮并根据我的后退按钮功能使其工作,我该怎么做?我在网上搜索了很多天,但后退导航对我来说是一个巨大的问题。你能帮我解决这个问题吗..
    • 如果有后台任务不取消,继续执行。所以以前的堆栈不会被这个破坏:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-24
    • 1970-01-01
    • 2019-03-08
    • 2017-07-27
    • 1970-01-01
    • 2016-03-09
    • 1970-01-01
    相关资源
    最近更新 更多