在prism模块化时,IRegion提供了添加View和Remove的方法.下面对一些会遇到的问题进行讨论。
以下为Demo的Shell,一个Menu的Region,两个内容区域.
<StackPanel> <Menu cal:RegionManager.RegionName="TopRegion" ></Menu> <StackPanel Orientation="Horizontal"> <GroupBox Header="LeftRegion" cal:RegionManager.RegionName="LeftRegion" Width="300" Height="600"> </GroupBox> <GroupBox Header="RightRegion" cal:RegionManager.RegionName="RightRegion" Width="300" Height="600"> </GroupBox> </StackPanel> </StackPanel>
问题:多个模块组成在一起,不可能是同时初始化时,全部加载的.如下图,模块未加载之前.
点击菜单加载一个登录的模块以后,如下图
解决办法:模块初始化时,不要加载页面,注册模块的相关服务即可.
如下面左右两个区域加载了同个登录控件.
问题:在我们注册对象时,一个控件实例是无法同时在两个区域中的.如果系统用这种同个区域使用多个模块的话,则不要注册单一实例,如
_unityContainer.RegisterType<LoginView>(new ContainerControlledLifetimeManager());
_regionManager.Regions["LeftRegion"].Add(_unityContainer.Resolve<LoginView>());
_regionManager.Regions["RightRegion"].Add(_unityContainer.Resolve<LoginView>());
解决办法:所以当你加载此模块时,需保证加载的控件是新的一个实例.
_regionManager.Regions["LeftRegion"].Add(new LoginView()); _regionManager.Regions["RightRegion"].Add(new LoginView());
问题:子控件区域再添加子控件时如上一样,依然需要重新实例化
//second time will throw exception _regionManager.AddToRegion("LoginRegion", _unityContainer.Resolve<HelloWorldView>());
当LoginRegionView移除之后,HelloWorldView依然存在容器中
解决方法:
(1)同上,还是需要一个新的实例对象.
(2)将LoginRegionView也存在容器中,也可以解决此问题,但不符合多个区域同时加载同个模块的需求
加载ui最好是延迟加载(按需加载),这样程序的初始化和运行速度都会加快.有时候我们会犯一些错误,向一个Region中添加一个View.
如点击MenuItem添加一个View,这个View应该是MenuItem的Click事件触发后才初始化.如下代码:
private void AddViewToRegion(object view) { MenuItem regionItem = new MenuItem() { Header = "加载模块" }; regionItem.Click+=new RoutedEventHandler((o,e) => { _regionManager.Regions["region"].Add(view); }); }
然后调用,传入的参数是一个UserControl,注意这里传入参数的时候就已经初始化了.不符合要求.
AddViewToRegion(new HelloWorldView());
现在代码如下:
private void AddViewToRegion(Func<object> view) { MenuItem regionItem = new MenuItem() { Header = "加载模块" }; regionItem.Click+=new RoutedEventHandler((o,e) => { _regionManager.Regions["region"].Add(view()); }); } AddViewToRegion(() => new HelloWorldView());