我有使用PRISM 4的silverlight 4应用程序,我正在使用MEF。
我的Shell定义了一个加载模块的主要区域,我希望模块有自己的RegionManager,因此它们定义的区域是本地RegionManager而不是global的位置。并且我想在模块内部通过容器(对于类型IRegionManager)解析此本地RegionManager。
然而,来自文档的方法:
IRegion detailsRegion = this.regionManager.Regions["DetailsRegion"];
View view = new View();
bool createRegionManagerScope = true;
IRegionManager detailsRegionManager = detailsRegion.Add(view, null,
createRegionManagerScope);
对我来说不起作用,当从子视图中解析IRegionManager时,我仍然得到GlobalRegionManager。
答案 0 :(得分:10)
我和你的情况相同,我有一个嵌套的区域经理,但所有的子视图仍然是全球区域经理。我提出了我认为合理的解决方案。
首先我定义一个接口:
/// <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;
}
然后你需要做的就是在你的view / viewmodel上实现IRegionManagerAware
,可能是这样的:
public class MyView : IRegionManagerAware
{
IRegionManager RegionManager { set; get; }
}
然后,当此视图添加到区域时,该行为将正确地将RegionManager
属性设置为当前作用域区域管理器。
答案 1 :(得分:2)
如果您阅读文档中的下一行,请说明 “Add方法将返回视图可以保留的新RegionManager,以便进一步访问本地范围。”
所以我会在视图中创建一个属性并将IRegionManger传递给它。
在你的view / viewModel。中public IRegionManager rm { get; set; }
然后传递添加新视图后返回的IregionManager
view.rm = detailsRegionManager;
希望有所帮助。