Scoped RegionViewRegistry?

Topics: Prism v4 - WPF 4
Jul 30, 2013 at 9:23 PM
I have a case where I'm displaying modal windows. These windows each have their own child container (unity CreateChildContainer()) and sub region manager (CreateRegionManager()).

As I understand it, when using scoped regions it is generally necessary to inject views into the appropriate regions.

It seems that PRISM is very close to being able to support discovery in this situation if only there were the concept of scoped RegionViewRegistry. As it is, when a sub region manager is created, it's method RegisterViewWithRegion() still uses the main registry.

I would like the ability to do something like the following each time a modal window is shown:
// Registry dependencies that ViewType may have
childContainer.RegisterType<IA,A>(new ContainerControlledLifetimeManager());
childContainer.RegisterType<IB,B>(new ContainerControlledLifetimeManager());

// Register view with region using delegate that builds view on the child container
    () => childContainer.Resolve(ViewType));
As it is, RegisterViewWithRegion seems to persist the delegate that was registered causing havoc the second time a modal window is shown and this code is repeated.

Are there any patterns for getting around this problem aside from directly injecting the view into the region?

Jul 31, 2013 at 9:25 PM

As out of the box the RegionViewRegistry provided by Prism is used for the entire application and it does not allow to remove a previous registration. Hence in order to acquire the functionality you are describing you will need to take advantage of the extension points provided by Prism to implement you own custom logic.

A possible approach for example could be to use the implementation provided in the following blog post:
This approach basically allows to define a view registration only for an specific RegionManager. If you are using a scoped RegionManager for each window then you could register the view with said region manager each time a window is shown. As each window will have its own RegionManager, you should not experience issues with the previous registrations.
However, this approach also creates other problems. First, the previous delegates will be still stored in the RegionViewRegistry, which could cause memory leaks. Second, if the RegionManagers of two windows are identical, they might return the same hash code, making this approach pointless for this scenario.

Another approach could be to use to create a scoped RegionViewRegistry for each window. Basically what defines the "scope" where the registration of the views will have effect are the AutoPopulateRegionBehaviors that are subscribed to the RegionViewRegistry. By default, those behaviors subscribe to the global RegionViewRegistry, but I believe they could be created manually passing them the scoped RegionViewRegistry they should subscribe to in its constructor. Then you just need to replace the behavior in the region using the same behavior key. The problem with this approach is that you will need to access the Region itself to change the AutoPopulateRegionBehavior and if you have access to the region it would be easier to simply inject the view in it manually.

As it can be seen, trying to implement this functionality using the RegionViewRegistry is not a trivial task.

In my opinion, the easiest approach is to inject the view directly instead of using the RegionViewRegistry. The functionality that the registry provides can be simply obtained by first checking if a Region exist. If not, then you can subscribe to the CollectionsChanged event of the Regions collection in the scoped RegionManager. When a Region is added to the RegionManager, the event will be fired allowing you to add the corresponding views to the Region.

I hope this helps,

Damian Cherubini
Aug 14, 2013 at 2:07 AM
Thanks as always Damian...

I will take the injection route in the short term but hope to look into a scoped RegionManager solution when time allows.

-- Terrence