WPF/Prism 库和多个 shell

标签 wpf prism

我对 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/

相关文章:

silverlight - 减慢 Silverlight Prism 模块加载速度的最佳/标准方法(用于测试)

wpf - 使用 ObjectDataProvider

wpf - 什么可以阻止 MEF 或 Prism 加载我的类型?

c# - PRISM中的复合 View 导航

c# - 处理这两个依赖于另一个的异步方法的最佳方法是什么?

c# - 如何防止来自未知插件的方法调用

c# - 这个 viewModel 是如何创建的?

c# - 作为基础的通用类导致 XAML 错误

c# - 将 ViewModel 引用传递给另一个 ViewModel(绑定(bind)到 View 的同一引用)?

c# - 如何在代码中为 DataTemplate 分配事件处理程序?