【问题标题】:Prism 4 - locally scoped RegionManagerPrism 4 - 本地范围的 RegionManager
【发布时间】:2011-07-05 12:25:32
【问题描述】:

我有带 PRISM 4 的 silverlight 4 应用程序,我正在使用 MEF。

我的 Shell 定义了一个加载模块的主要区域,我希望模块有自己的 RegionManager,因此它们定义的区域是本地 RegionManager 中的位置,而不是全局的。我希望这个本地 RegionManager 在模块内部时由容器(对于 IRegionManager 类型)解析。

但是文档中的方法:

IRegion detailsRegion = this.regionManager.Regions["DetailsRegion"];
View view = new View();
bool createRegionManagerScope = true;
IRegionManager detailsRegionManager = detailsRegion.Add(view, null, 
                            createRegionManagerScope);

对我不起作用,从子视图内部解析 IRegionManager 时,我仍然得到 GlobalRegionManager。

【问题讨论】:

    标签: c# silverlight silverlight-4.0 prism mef


    【解决方案1】:

    我的情况和你一样,我有一个嵌套的区域管理器,但是所有的子视图仍然是全局区域管理器。我想出了我认为合理的解决方案。

    首先我定义一个接口:

    /// <summary>
    /// An interface which is aware of the current region manager.
    /// </summary>
    public interface IRegionManagerAware
    {
        /// <summary>
        /// Gets or sets the current region manager.
        /// </summary>
        /// <value>
        /// The current region manager.
        /// </value>
        IRegionManager RegionManager { get; set; }
    }
    

    然后我像这样设置RegionBehavior

    /// <summary>
    /// A behaviour class which attaches the current scoped <see cref="IRegionManager"/> to views and their data contexts.
    /// </summary>
    public class RegionAwareBehaviour : RegionBehavior
    {
        /// <summary>
        /// The key to identify this behaviour.
        /// </summary>
        public const string RegionAwareBehaviourKey = "RegionAwareBehaviour";
    
        /// <summary>
        /// Override this method to perform the logic after the behaviour has been attached.
        /// </summary>
        protected override void OnAttach()
        {
            Region.Views.CollectionChanged += RegionViewsChanged;
        }
    
        private void RegionViewsChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            Contract.Requires<ArgumentNullException>(e != null);
    
            if (e.NewItems != null)
                foreach (var item in e.NewItems)
                    MakeViewAware(item);
        }
    
        private void MakeViewAware(object view)
        {
            Contract.Requires<ArgumentNullException>(view != null);
    
            var frameworkElement = view as FrameworkElement;
            if (frameworkElement != null)
                MakeDataContextAware(frameworkElement);
    
            MakeAware(view);
        }
    
        private void MakeDataContextAware(FrameworkElement frameworkElement)
        {
            Contract.Requires<ArgumentNullException>(frameworkElement != null);
    
            if (frameworkElement.DataContext != null)
                MakeAware(frameworkElement.DataContext);
        }
    
        private void MakeAware(object target)
        {
            Contract.Requires<ArgumentNullException>(target != null);
    
            var scope = target as IRegionManagerAware;
            if (scope != null)
                scope.RegionManager = Region.RegionManager;
        }
    }
    

    然后将其应用于引导程序中的所有区域:

    protected override IRegionBehaviorFactory ConfigureDefaultRegionBehaviors()
    {
        var behaviours = base.ConfigureDefaultRegionBehaviors();
    
        behaviours.AddIfMissing(RegionAwareBehaviour.RegionAwareBehaviourKey, typeof(RegionAwareBehaviour));
    
        return behaviours;
    }
    

    那么你所要做的就是在你的视图/视图模型上实现IRegionManagerAware,可能是这样的:

    public class MyView : IRegionManagerAware
    {
        IRegionManager RegionManager { set; get; }
    }
    

    然后当这个视图被添加到一个区域时,该行为会正确地将RegionManager 属性设置为当前作用域的区域管理器。

    【讨论】:

    • 非常好。我仍在使用 PRISM,但它几乎被完全重写了。 Prism 有一个很好的可扩展架构。
    • 效果很好。我只禁用了合同
    【解决方案2】:

    如果您阅读文档中的下一行,它会说 “Add 方法将返回视图可以保留的新 RegionManager,以便进一步访问本地范围。”

    所以我会在视图中创建一个属性并将 IRegionManger 传递给它。

    在您的视图/视图模型中。

    public IRegionManager rm { get; set; }
    

    然后传递添加新视图后返回的 IregionManager

    view.rm = detailsRegionManager;
    

    希望对您有所帮助。

    【讨论】:

    • 确实,我希望它能够集成到 IoC 并正确解析 RegionManager,但看起来你需要自己管理它。
    • @AlexBurtsev 看看我最近的回答,我相信我已经找到了一个手动接线的解决方案。
    猜你喜欢
    • 2011-08-28
    • 1970-01-01
    • 2012-08-29
    • 2016-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多