I have silverlight 4 application with PRISM 4, I\'m using MEF.
My Shell defines one main region in which modules are loaded, I want modules to have their own RegionManag
I was in the same situation as you, I had a nested region manager, but all of the child views were still getting the global region manager. I came up with what I consider a reasonable solution.
First I define an interface:
///
/// An interface which is aware of the current region manager.
///
public interface IRegionManagerAware
{
///
/// Gets or sets the current region manager.
///
///
/// The current region manager.
///
IRegionManager RegionManager { get; set; }
}
Then I setup a RegionBehavior
like so:
///
/// A behaviour class which attaches the current scoped to views and their data contexts.
///
public class RegionAwareBehaviour : RegionBehavior
{
///
/// The key to identify this behaviour.
///
public const string RegionAwareBehaviourKey = "RegionAwareBehaviour";
///
/// Override this method to perform the logic after the behaviour has been attached.
///
protected override void OnAttach()
{
Region.Views.CollectionChanged += RegionViewsChanged;
}
private void RegionViewsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Contract.Requires(e != null);
if (e.NewItems != null)
foreach (var item in e.NewItems)
MakeViewAware(item);
}
private void MakeViewAware(object view)
{
Contract.Requires(view != null);
var frameworkElement = view as FrameworkElement;
if (frameworkElement != null)
MakeDataContextAware(frameworkElement);
MakeAware(view);
}
private void MakeDataContextAware(FrameworkElement frameworkElement)
{
Contract.Requires(frameworkElement != null);
if (frameworkElement.DataContext != null)
MakeAware(frameworkElement.DataContext);
}
private void MakeAware(object target)
{
Contract.Requires(target != null);
var scope = target as IRegionManagerAware;
if (scope != null)
scope.RegionManager = Region.RegionManager;
}
}
Then apply this to all regions in your bootstrapper:
protected override IRegionBehaviorFactory ConfigureDefaultRegionBehaviors()
{
var behaviours = base.ConfigureDefaultRegionBehaviors();
behaviours.AddIfMissing(RegionAwareBehaviour.RegionAwareBehaviourKey, typeof(RegionAwareBehaviour));
return behaviours;
}
Then all you have to do is implement IRegionManagerAware
on your view/viewmodel, probably like so:
public class MyView : IRegionManagerAware
{
IRegionManager RegionManager { set; get; }
}
Then when this view is added to a region, the behaviour will correctly set the RegionManager
property to the currently scoped region manager.