Register a Scoped Region Manager – Best Practise?

Topics: Prism v2 - Silverlight 2, Prism v2 - WPF 3.5
Apr 22, 2009 at 7:08 AM

Hi all,

I have a view that has several regions with static region names.  This view is reused many times to define layouts of other views.  I’m using scoped region managers to avoid errors related to the reuse of same region names.  We are also using dependency injection to inject the region manager into our classes, it appears the region manager that is injected each time is the primary region manager registered by the shell.  The problem is we don’t always want the primary region manager, instead we want a scoped region manager.

For each module we have the module initialiser class, it’s here where we create a scoped region manager, we would like all presentation model classes from this point on for this module to use the scoped region manager, I doubt dependency injection is going to work to give us the scoped manager each time, so I’m wondering if its ok to register the scoped manager instance with the container so it can be accessed by our presentation model classes, or it there a more appropriate way?

Here’s an example:

IRegionManager region2 = mRegionManager.Regions[RegionNames.MainZone].Add(layout.View, RegionNames.ServiceRegion, true);
this.container.RegisterInstance("ServiceRegionManager", region2);

Thanks

Paul

Apr 22, 2009 at 12:07 PM
Hi Paul,

I've created a LayoutManager for Prism v2, which may help.

http://www.codeproject.com/KB/WPF/PrismLayoutManager.aspx

I'm getting ready to post an update which allows you to define layouts in Xaml as well as in the app.config.

If you're interested I can send you the source code.

Cheers

Ron
Apr 22, 2009 at 1:40 PM

Thanks Ron, I downloaded your Layout Manager and it’s very cool indeed, however I’m not sure it solves my issue, ultimately I would like to know how I can change a region name at runtime successfully, when I’ve tried the region manager never becomes aware of the changed region name and an exception is thrown stating the region name is already registered and digging deeper the region name I changed doesn’t appear in the region manager anywhere.

For example I have a layout view which consists of a tab control with a region name of TabRegion, I have a starting module which registers the layout view with the main shell region, my 24 other modules are required to create a new instance of the layout view and push it into the TabRegion creating a tab control in each tab item in TabRegion.  I would like for each module to be able to create a new instance of the layout view, change the region name so there are no conflicts.  I tried Binding etc without any success.  To date to get around this I create scoped region manager to avoid region name conflicts and then I have no option to then register the scoped region manager in the container so module controllers etc can access it HOWEVER this is purely crazy as each module can potentially reuse the layout view 9 times.

Do you know how to change a region name for a new layout view instance at runtime or a better approach??

Thanks

Paul

Apr 22, 2009 at 3:29 PM
Hey Paul,

I think I understand what it is you're trying to do.  It would help if I had some code to look at.  Anyway... I'm assuming you are using the RegionManager.RegionName attached properties on your layout controls?  If so, have you tried not using them and instead use the RegionManager.SetRegionName method to specify the region name on the target control.  I suspect all the regions have already been registered by the time you are attempting to change them.  I found there is much more happening behind-the-scenes when regions are registered (behaviours, listeners, adapters, etc).  Setting them in code is not ideal, but it's worth a try just to see what happens.

If you want to send me some sample code I'm at: ron at gramann dot co dot uk

Good luck!

rg
Oct 28, 2009 at 11:13 AM
Edited Oct 28, 2009 at 11:32 AM

I'm thinking that you can try the following:  (please feel free to replace the word unity with the IoC container brand you favor ;) )

  1. Inject a view (which will function as a host control) into the parent region, which returns a scoped region manager. 
  2. Create a child unity container from the main unity container.
  3. Place the scoped region manager in the child unity container
  4. Use the child unity container to construct your view &/or view model &/or model (etc.)
  5. Attach the resulting "your view" to the "host view" (or replace it if you prefer)

Code (not compiled, let alone tested :) )

 

IRegion detailsRegion = this.regionManager.Regions["DetailsRegion"];

HostView hostView = this.container.Resolve<HostView>();
IRegionManager scopedRegionManager = detailsRegion.Add(hostView, null, true);

// optionally activate the view (if DetailsRegion is a tab control, this gives the new hostView's tab the focus)
detailsRegion.Activate(hostView);

UnityContainer childContainer = this.container.CreateChildContainer();
childContainer.RegisterInstance<IRegionManager>(scopedRegionManager);
hostView.ChildContainer = childContainer; // someone should look after the new child container

MyView myView = childContainer.Resolve<MyView>();
hostView.Content = myView;

The HostView guy can display loading visuals for the user while things are loading up...  especially good for delayed module loading strategies not shown here...

I'm thinking that this approach will work recursively, implementing the Composite View pattern in which a recursive UI structure of views is composed by a mechanism at runtime...

Jun 24, 2010 at 1:07 PM

I dont understand this line:

hostView.ChildContainer = childContainer;
Is this some property in hostview? How can you reuse childcontainer in multiple modules because I need to use layoutView in different modules who inject their views?