Multiple shells and shared view among modules

Topics: Prism v4 - WPF 4
May 10, 2011 at 7:08 PM


I'm pretty new with Prism and after playing a bit around, there a few questions that arise. I'm trying to create a modular application that basically contains a map control in a shell window. The plugin modules offer different tools for interacting with the map. Some of the modules are pretty independent and simply display pins on the map.

- 1st question: How would RegionManager come into play for the module-specific classes (presenters) that must interact with the main map control? Usually in a RegionManager you register a specific view which is linked to a ViewModel, but in my case there is one single view (the map view) with multiple presenters acting on it.

- 2nd question: I need to be able to open several windows (shells) -- a bit like an MS Word document -- that should all be extended by the plugin modules. In a single-shell environment, when the module specific classes were instantiated, they could use the Dependency Injection Container to get a reference to the RegionManager or the Shell itself in order to get access to the map control. However with multiple shells, I don't see how to get access to the map control of the right shell. The dependency container has references to object global to the application, not specific for the shell I'm currently working in. Same is true for the EventAggregator.

Any input would be very welcome,

May 10, 2011 at 10:43 PM

To make my 2nd question a bit more clear: Chrome & Firefox can have plugins that add new visual elements to the toolbars, etc. Each time you open a new browser window, they all contain the extensions applied by the plugins. So that's pretty much what I'm trying to achieve when I say open several windows.

May 11, 2011 at 7:28 PM
Edited May 12, 2011 at 5:21 PM

After hours of reading Prism-related articles and forums I've come across the article "How to build an outlook style application" on Erwin van der Valk's Blog ( 

In one part of the architecture, a Unity Child Container was used to resolve type instances. That's exactly what I needed for the answer to my 2nd question: I needed to have "scoped" (by window) dependency injection (ex: window scoped EventAggregator, Map control, etc.).

Here's how I create a new window:


    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;


So MapDocumentView and all its components will be injected (if needed) window-scoped instances.
Now that I can have scoped injected objects, I can get the window-scoped map in my module-based MapPresenter. To answer my 1st question, I defined an interface IHostApplication which is implemented by the Bootstrapper which has a MapPresenterRegistry property. This interface is added to the main container.  Upon initialization, the modules will register their presenters and upon the window creation, they will be instantiated.

So for the module initialization:

    public void Initialize() 


The code that initializes the map window:

    private void View_Loaded(object sender, RoutedEventArgs e)
      // Register map in the == scoped container ==
      // 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)


The module-specific MapPresenter:

    public ModuleSpecificMapPresenter(IEventAggregator eventAggregator, IMap map)
      this.eventAggregator = eventAggregator; = map;
      // Do stuff on with the map


So those are the big lines of my solution. What I don't really like is that I don't take advantage of region management this way. I pretty much have custom code to do the work.
If you have any further thoughts, I would be happy to hear them out.