Prism 4 - locally scoped RegionManager

前端 未结 2 563
半阙折子戏
半阙折子戏 2021-02-09 19:07

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

2条回答
  •  谎友^
    谎友^ (楼主)
    2021-02-09 19:42

    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.

提交回复
热议问题