Prism 4-本地范围的RegionManager

本文关键字:RegionManager 范围 4-本 Prism | 更新日期: 2023-09-27 18:01:04

我有带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。

Prism 4-本地范围的RegionManager

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

首先我定义了一个接口:

/// <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属性设置为当前作用域的区域管理器。

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

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

在视图/viewModel中。

public IRegionManager rm { get; set; }

然后通过添加新视图后返回的IregionManager

view.rm = detailsRegionManager;

希望能有所帮助。