现在的位置: 首页 > 综合 > 正文

[Silverlight入门系列]关于Prism的Scoped RegionManager

2012年09月02日 ⁄ 综合 ⁄ 共 4963字 ⁄ 字号 评论关闭

如果你用Prism框架,那么请继续阅读本文,有关Scoped RegionManager的。Prism框架中有RegionManager,可以用构造注入IRegionManager的方式获得全局的RegionManager。今天要说的不是全局的RegionManager,而是Scoped RegionManager,也就是说在作用域内的RegionManager,什么意思?如果你的应用包含复杂的Region嵌套,例如,你的应用整体有一个大的TabRegion,每次打开一个Tab就是注入一个View,在每个View里面又各自包含TabRegion,里面每次打开一个Tab就是注入一个View,在每个View里面又各自包含TabRegion…..这样就是一个复合模式的Region嵌套了,这个时候,你如果关闭一个Tab又打开一个tab,或者打开多个同类型的tab,那就会遇到下列异常:

 

An exception occurred while trying to create region objects.
    - The most likely causing exception was: 'System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. --->
    Microsoft.Practices.Prism.Regions.Behaviors.RegionCreationException: An exception occurred while creating a region with name subTabSubRegion.
    The exception was: System.ArgumentException: Region with the given name is already registered: subTabSubRegion
   at Microsoft.Practices.Prism.Regions.RegionManager.RegionCollection.Add(IRegion region)
   at Microsoft.Practices.Prism.Regions.Behaviors.RegionManagerRegistrationBehavior.TryRegisterRegion()
   at Microsoft.Practices.Prism.Regions.Behaviors.RegionManagerRegistrationBehavior.StartMonitoringRegionManager()
   at Microsoft.Practices.Prism.Regions.Behaviors.RegionManagerRegistrationBehavior.OnAttach()
   at Microsoft.Practices.Prism.Regions.RegionBehavior.Attach()
   at Microsoft.Practices.Prism.Regions.RegionBehaviorCollection.Add(String key, IRegionBehavior regionBehavior)
   at Microsoft.Practices.Prism.Regions.RegionAdapterBase`1.AttachDefaultBehaviors(IRegion region, T regionTarget)
   at Microsoft.Practices.Prism.Regions.RegionAdapterBase`1.Initialize(T regionTarget, String regionName)
   at Microsoft.Practices.Prism.Regions.RegionAdapterBase`1.Microsoft.Practices.Prism.Regions.IRegionAdapter.Initialize(Object regionTarget, String regionName)
   at Microsoft.Practices.Prism.Regions.Behaviors.DelayedRegionCreationBehavior.CreateRegion(DependencyObject targetElement, String regionName).  ---> System.ArgumentException: Region with the given name is already registered: SubDevicesRegion
   at Microsoft.Practices.Prism.Regions.RegionManager.RegionCollection.Add(IRegion region)
   at Microsoft.Practices.Prism.Regions.Behaviors.RegionManagerRegistrationBehavior.TryRegisterRegion()
   at Microsoft.Practices.Prism.Regions.Behaviors.RegionManagerRegistrationBehavior.StartMonitoringRegionManager()
   at Microsoft.Practices.Prism.Regions.Behaviors.RegionManagerRegistrationBehavior.OnAttach()
   at Microsoft.Practices.Prism.Regions.RegionBehavior.Attach()
   at Microsoft.Practices.Prism.Regions.RegionBehaviorCollection.Add(String key, IRegionBehavior regionBehavior)
   at Microsoft.Practices.Prism.Regions.RegionAdapterBase`1.AttachDefaultBehaviors(IRegion region, T regionTarget)
   at Microsoft.Practices.Prism.Regions.RegionAdapterBase`1.Initialize(T regionTarget, String regionName)
   at Microsoft.Practices.Prism.Regions.RegionAdapterBase`1.Microsoft.Practices.Prism.Regions.IRegionAdapter.Initialize(Object regionTarget, String regionName)
   at Microsoft.Practices.Prism.Regions.Behaviors.DelayedRegionCreationBehavior.CreateRegion(DependencyObject targetElement, String regionName)
   --- End of inner exception stack trace ---
   at Microsoft.Practices.Prism.Regions.Behaviors.DelayedRegionCreationBehavior.CreateRegion(DependencyObject targetElement, String regionName)
   at Microsoft.Practices.Prism.Regions.Behaviors.DelayedRegionCreationBehavior.TryCreateRegion()
   at Microsoft.Practices.Prism.Regions.Behaviors.DelayedRegionCreationBehavior.OnUpdatingRegions(Object sender, EventArgs e)
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
   at System.Delegate.DynamicInvokeImpl(Object[] args)
   at System.Delegate.DynamicInvoke(Object[] args)
   at Microsoft.Practices.Prism.Events.WeakDelegatesManager.Raise(Object[] args)
   at Microsoft.Practices.Prism.Regions.RegionManager.UpdateRegions()'.

 

解决这个问题的方法就是用Scoped Region,比如在打开的DetailsView的时候,用IRegionManaer r = region.add(view, key, true)方法,然后用创建的Scoped RegionManager新实例来打开新的视图,而不是用GLobal RegionManager。代码:

   1: //注意返回值,注意最后一个参数

   2: IRegionManager detailsRegionManager = 

   3:   detailsRegion.Add(detailsPresenter.View,

   4:   employee.EmployeeId.ToString(CultureInfo.InvariantCulture), true);

   5:  

   6: //用上面Scoped Regionmanager 新实例来加视图!

   7: IRegion region = detailsRegionManager.Regions[RegionNames.TabRegion];

   8: region.Add(projectsListPresenter.View, "CurrentProjectsView");

   9: detailsRegion.Activate(detailsPresenter.View);

如果你用MVVM模式来开发,而且每次打开新的视图都是独立的MVVM的模式,那么问题就来了,这个Scoped RegionManager如何传递到新的视图的ViewModel?这就是ViewModel之间如何传递数据传参数的问题了。我使用扩展方法扩展了regionManager.RequestNavigate方法,添加ComplexData参数,这样我就可以把IRegionManager(Scoped RegionManager)放在ComplexData参数里面,用regionManager.RequestNavigate方法传递到新建View的ViewModel里面去,完全是两个ViewModel间传递参数。具体代码参考我的另外一篇博文,这里不重复了。

 

有关Scoped RegionManager其它资源:

抱歉!评论已关闭.