我对 Prism 还很陌生,玩了一会儿之后,出现了一些问题。我正在尝试创建一个模块化应用程序,它基本上在 shell 窗口中包含一个 map 控件。插件模块提供了与 map 交互的不同工具。一些模块非常独立,只是在 map 上显示图钉。
第一个问题:对于必须与主 map 控件交互的特定于模块的类(呈现器),RegionManager 将如何发挥作用?通常在 RegionManager 中,您注册一个链接到 ViewModel 的特定 View ,但在我的例子中,只有一个 View ( map View ),多个演示者对其进行操作。
第二个问题:我需要能够打开几个窗口(外壳)——有点像 MS Word 文档——它们都应该由插件模块扩展。在单 shell 环境中,当模块特定类被实例化时,它们可以使用依赖注入(inject)容器来获取对 RegionManager 或 Shell 本身的引用,以便访问 map 控件。但是,对于多个 shell,我看不到如何访问正确 shell 的 map 控件。依赖项容器引用了应用程序的全局对象,而不是我当前正在使用的 shell 的特定对象。EventAggregator 也是如此。
欢迎任何意见
埃德
最佳答案
在阅读 Prism 相关文章和论坛数小时后,我在 Erwin van der Valk 的博客上看到了文章“如何构建 outlook 风格的应用程序”- How to Build an Outlook Style Application .
在架构的一部分中,Unity 子容器用于解析类型实例。这正是我回答第二个问题所需要的:我需要有“作用域”(按窗口)依赖注入(inject)(例如:窗口作用域 EventAggregator、 map 控件等)
下面是我如何创建一个新窗口:
private IShellWindow CreateNewShell(IRegionManager regionManager)
{
IUnityContainer childContainer = this.Container.CreateChildContainer();
... register types in child container ...
var window = new ShellWindow();
RegionManager.SetRegionManager(window, regionManager);
window.Content = childContainer.Resolve<MapDocumentView>();
return window;
}
因此 MapDocumentView 及其所有组件将被注入(inject)(如果需要)窗口范围的实例。
现在我可以在范围内注入(inject)对象,我可以在基于模块的 MapPresenter 中获取窗口范围内的 map 。为了回答我的第一个问题,我定义了一个接口(interface) IHostApplication,它由具有 MapPresenterRegistry 属性的 Bootstrapper 实现。此接口(interface)添加到主容器中。
初始化时,模块将注册它们的呈现器,并且在创建窗口时,它们将被实例化。
所以对于模块初始化:
public void Initialize()
{
...
this.hostApplication.MapPresenterRegistry.Add(typeof(ModuleSpecificMapPresenter));
...
}
初始化 map 窗口的代码:
private void View_Loaded(object sender, RoutedEventArgs e)
{
// Register map in the == scoped container ==
container.RegisterInstance<IMap>(this.View.Map);
// Create map presenters
var hostApplication = this.container.Resolve<IHostApplication>();
foreach (var mapPresenterType in hostApplication.MapPresenterRegistry)
{
var mapPresenter = this.container.Resolve(mapPresenterType) as IMapPresenter;
if (mapPresenter != null)
{
this.mapPresenters.Add(mapPresenter);
}
}
}
特定于模块的 MapPresenter:
public ModuleSpecificMapPresenter(IEventAggregator eventAggregator, IMap map)
{
this.eventAggregator = eventAggregator;
this.map = map;
this.eventAggregator.GetEvent<AWindowSpecificEvent>().Subscribe(this.WindowSpecificEventFired);
// Do stuff on with the map
}
这些就是我的解决方案的主要内容。我不太喜欢的是我没有以这种方式利用区域管理。我几乎有自定义代码来完成这项工作。
如果您有任何进一步的想法,我很乐意听取他们的意见。 爱德华
关于WPF/Prism 库和多个 shell,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5954673/