当托管在 MFC CView 中时,Prism shell 区域不会填充

发布于 2025-01-05 06:03:22 字数 959 浏览 5 评论 0原文

我们正在开发一个使用 C#、WPF4、Prism4 和 MEF 的新应用程序。该应用程序包括一个主 shell 窗口,它定义了一个带有一些拆分器和五个区域的网格,以及许多单独的模块,这些模块通过视图发现和视图注入向各个区域提供 UI 功能。所有标准的东西,没有什么异国情调。该应用程序非常基本,一切都工作正常,即模块在运行时正确地将其视图贡献到 shell 的区域中。

我们还需要将相同的 shell(以及来自贡献模块的 UI)托管到我们拥有的大型遗留 MFC 应用程序中。这就是我们遇到问题的地方。 WPF/MFC 互操作代码(使用 HwndSource)似乎工作正常,外壳作为父 MFC CView 的子级正确显示,并且具有外壳本身定义的网格分割器等基本功能,这一事实证明了这一点。然而,shell 中的任何区域都没有填充 Prism 模块中定义的视图。调试显示模块确实正在加载,但是,注入到每个模块的 IRegionManager 实例包含零个区域,供模块添加其视图。就好像 Prism 根本不知道 shell 定义了任何区域,因此,尝试将视图添加到这些“不存在”的区域会失败。

我们派生了一个新的自定义引导程序类,我们的 MFC 代码在该类上调用 Run() 方法。这个引导程序类与独立应用程序中的等效类相同(工作正常),唯一的区别是我们不再重写 InitializeShell() 方法,我们只依赖基类实现。通常,会重写此方法以将 Application.Current.MainWindow 设置为 shell,然后显示 shell,但是,在我们的示例中,没有当前应用程序,因为我们托管在 MFC 应用程序内。重写 Bootstrapper 的运行功能以将控制权交还给 MFC 应用程序以在适当的时间显示 shell 的各种尝试都失败了(失败是指 shell 的区域仍未填充,但 shell 仍然显示)。

有人在 MFC 应用程序中成功使用 Prism 4(特别是填充了 shell 区域)吗?任何关于如何在 MFC CView 中托管具有区域的启用 Prism 的 shell 以及如何让 MFC 应用程序启动引导过程的建议将不胜感激。谢谢。

We are working on a new application that uses C#, WPF4, Prism4 and MEF. The application comprises a main shell window which defines a grid with some splitters and five regions, and a number of separate modules that contribute UI functionality in to the various regions through view discovery and view injection. All standard stuff, nothing exotic. The application is very basic and everything works fine, i.e. the modules correctly contribute their views in to the shell's regions at run time.

We also have a requirement to host the same shell (and UI from the contributing modules) in to a large legacy MFC application we have. Here's where we're having problems. The WPF/MFC interop code (using HwndSource) seems to be working fine, as evidenced by the fact that the shell gets displayed correctly as a child of the parent MFC CView and has basic functionality like a grid splitter that is defined in the shell itself. However, none of the regions in the shell are being populated with views defined in the Prism modules. Debugging shows that the modules are indeed being loaded, however, the IRegionManager instance that gets injected in to each module contains zero regions for the module to add its views in to. It's as if Prism is not aware that the shell defines any regions at all, consequently, attempts to add views in to these "non-existent" regions fail.

We derived a new custom bootstrapper class that our MFC code calls the Run() method on. This bootstrapper class is identical to its equivalent in the standalone application (which works fine), the only difference is that we no longer override the InitializeShell() method, we just rely on the base class implementation. Typically this method is overridden to set the Application.Current.MainWindow to the shell and then show the shell, however, in our case there is no current application because we're hosted inside an MFC app. Various attempts at overriding the Bootstrapper's run functionality to yield control back to the MFC app to display the shell at the appropriate time have failed (failed in the sense that the shell's regions are still unpopulated, but the shell still displays).

Has anybody successfully used Prism 4 (specifically, got shell regions populated) within an MFC application? Any advice on how to host a Prism-enabled shell with regions in an MFC CView and have the MFC application initiate the bootstrapping process would be appreciated. Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我不吻晚风 2025-01-12 06:03:23

好吧,我明白了。在煞费苦心地逐步执行 Prism 代码时,我在 RegionManager 上发现了一个名为 OnSetRegionNameCallback() 的方法。此方法根据另一个方法调用 IsInDesignMode() 的结果有条件地调用 CreateRegion()。如果我们处于设计模式,则会创建一个区域,否则不会创建任何区域。对 IsInDesignMode 的仔细检查表明,进行了三个单独的测试来确定我们是否处于“设计模式”,如果其中任何一个为真,则认为我们处于设计模式。其中一项检查是 Application.Current == null。当然,在 MFC 应用程序的上下文中,Application.Current 确实为 null,因此(错误地)确定我们处于设计模式,因此从未创建任何区域。

当我意识到这一点后,进一步的互联网搜索显示许多其他人也遇到了同样的问题。事实上,CodePlex 的 Prism 部分甚至记录了一个问题(工作项目#3552)与这个追溯到 2009 年 1 月的确切问题有关。该工作项目的贡献者还建议了一种解决方法,即创建一个虚拟应用程序,只是为了传递“我们在设计中吗? 模式?”查看。请参考工作项目以了解更多详细信息。我实现了类似的解决方法,然后能够在 MFC 应用程序的 MFC CView 中成功托管启用 Prism 的 shell 及其贡献模块。

感谢那些在我面前开辟这条道路并确定并提出解决方法的人。你节省了我很多时间!

Okay, I figured it out. Painstakingly stepping through the Prism code, I came across a method on the RegionManager called OnSetRegionNameCallback(). This method conditionally calls CreateRegion() based on the result of another method call, IsInDesignMode(). If we are not in design mode, a region is created, otherwise no region is created. Closer examination of IsInDesignMode revealed that three separate tests are made to determine if we are in "design mode" or not, and if any of them are true, it is considered that we are in design mode. One of these checks was if Application.Current == null. Of course, in the context of an MFC application, Application.Current is indeed null, so the determination (erroneously) was that we were in design mode, and therefore no regions were ever created.

Once I realized this, further internet searches showed a number of other people have run in to the same problem. Indeed, there is even an issue logged in the Prism section of CodePlex (work item #3552) relating to this exact issue dating back to January 2009. Contributors to this work item also suggests a work around of creating a dummy application just to pass the "are we in design mode?" check. Please reference the work item for more details. I implemented a similar workaround and was then able to successfully host my Prism-enabled shell and its contributing modules in an MFC CView in an MFC application.

Thank you to those who blazed this trail before me and identified and proposed a workaround. You have saved me a lot of time!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文