Registering same module in different regions?

Topics: Prism v4 - WPF 4
Nov 6, 2010 at 11:47 PM

Hi,

I'm using Prism v4 with MEF and MVVM.
I have a CommandBarModule, that has a CommandBarView and a CommandBarViewModel. The goal of this module is to display a number of command buttons, loaded from the database.
In the shell view I have 4 regions (left, right, top, and bottom).

The goal is that there are 4 instances of the CommandBarModule, each instance being displayed in its own region. Each instance also has its own CommandBarViewModel, on which there's a Type property that indicates what kind of command bar type it is (left, right, top or bottom), so that the view model can correctly load the buttons that have to be displayed in it.

They all have to be initialized when the application starts, so it's not on demand.

I was thinking of implementing the Initialize method of the CommandBarModule, and for each region I would:

- resolve a CommandBarView instance
- resolve a CommandBarViewModel instance and set Type propery, when the model is constructed it loads the data needed to display its command buttons
- set the datacontext of the view to the model
- add the view to the correct region

But is this the correct way of achieving this? 

Nov 7, 2010 at 1:33 PM
Edited Nov 7, 2010 at 1:35 PM

Ok, I implemented a working solution, I believe it's an OK solution but feedback is welcome :)

First, in the bootstrapper of the shell I export the composition container:

 

[Export]
private static CompositionContainer _container { get; set; }

Of course in the bootstapper the _container has to be initialized, I think that COnfigureContainer method is the best place:

 

 

protected override void ConfigureContainer()
{            
            base.ConfigureContainer();
            _container = Container;
}

 

In the CommandBarModule, I use a controller to delegate the view injection work:

 

  [ModuleExport(typeof(CommandBarModule), InitializationMode = InitializationMode.WhenAvailable)]
    public class CommandBarModule : IModule
    {        
        private ICommandBarRegionController _commandBarRegionController;

        [ImportingConstructor]
        public CommandBarModule(ICommandBarRegionController commandBarRegionController)
        {            
            _commandBarRegionController = commandBarRegionController;
        }

        /// <summary>
        /// Notifies the module that it has to be initialized.
        /// </summary>
        public void Initialize()
        {
            // Initialize the CommandBarRegionController, which programmatically displays views in the Main region (using View Injection).
            _commandBarRegionController.InitializeInstances();
        }
    }

 

And in the controller, I can use the container to resolve instances of the view model and view for each region in the view:

 

[Export(typeof(ICommandBarRegionController))]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public class CommandBarRegionController : ICommandBarRegionController
    {
        private IRegionManager _regionManager;        

        [ImportingConstructor]
        public CommandBarRegionController(IRegionManager regionManager)
        {
            _regionManager = regionManager;           
        }

        [Import(AllowRecomposition = true)]
        private CompositionContainer _container { get; set; }

        public void InitializeInstances()
        {
            ICommandBarViewModel commandBarViewModel = _container.GetExportedValue<ICommandBarViewModel>();
            ICommandBarView commandBarView = _container.GetExportedValue<ICommandBarView>();
            commandBarView.ViewModel = commandBarViewModel;
            _regionManager.Regions[RegionNames.NorthRegion].Add(commandBarView);

            ICommandBarViewModel commandBarViewModel2 = _container.GetExportedValue<ICommandBarViewModel>();
            ICommandBarView commandBarView2 = _container.GetExportedValue<ICommandBarView>();
            commandBarView2.ViewModel = commandBarViewModel2;
            _regionManager.Regions[RegionNames.SouthRegion].Add(commandBarView2);            
        }
    }

 

 

 

 

 

Nov 7, 2010 at 2:01 PM
Edited Nov 7, 2010 at 3:07 PM

Ah and maybe little improvement by using constructor injection:

 

 [Export(typeof(ICommandBarRegionController))]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public class CommandBarRegionController : ICommandBarRegionController
    {
        private readonly IRegionManager _regionManager;
        private readonly ICommandBarViewModel _northCommandBarViewModel;
        private readonly ICommandBarViewModel _southCommandBarViewModel;
        private readonly ICommandBarView _northCommandBarView;
        private reaonly ICommandBarView _southCommandBarView;
        private CompositionContainer _container;

        [ImportingConstructor]
        public CommandBarRegionController(
            [Import(AllowRecomposition = true)]IRegionManager regionManager,
            [Import(AllowRecomposition = true, RequiredCreationPolicy=CreationPolicy.NonShared)] ICommandBarViewModel northCommandBarViewModel,
            [Import(AllowRecomposition = true, RequiredCreationPolicy = CreationPolicy.NonShared)] ICommandBarViewModel southCommandBarViewModel,
            [Import(AllowRecomposition = true, RequiredCreationPolicy = CreationPolicy.NonShared)] ICommandBarView northCommandBarView,
            [Import(AllowRecomposition = true, RequiredCreationPolicy = CreationPolicy.NonShared)] ICommandBarView southCommandBarView,
            [Import(AllowRecomposition = true, RequiredCreationPolicy = CreationPolicy.Shared)] CompositionContainer container
            )
        {
            _regionManager = regionManager;
            _northCommandBarViewModel = northCommandBarViewModel;
            _southCommandBarViewModel = southCommandBarViewModel;
            _container = container;
            _northCommandBarView = northCommandBarView;
            _southCommandBarView = southCommandBarView;
        }

        public void InitializeInstances()
        {                                    
            _northCommandBarView.ViewModel = _northCommandBarViewModel;
            _regionManager.Regions[RegionNames.NorthRegion].Add(_northCommandBarView);
                                   
            _southCommandBarView.ViewModel = _southCommandBarViewModel;
            _regionManager.Regions[RegionNames.SouthRegion].Add(_southCommandBarView);            
        }
    }