none
Prsim中View嵌套Region的问题 RRS feed

  • 问题

  • 问题1:在Prsim中,ModuleA调用IRegionManager.RegisterViewWithRegion方法,把View1注册到Region中。

    View1中包含了一个Region(名称为"View1Region"),当ModuleC调用IRegionManager.RegistrViewWithRegion("View1Region",typeof(ViewC));时,ViewC无法注册到View1Region中。(其中的IRegionManager为相同对象,由构造方法传入。

     

    问题2:有两个Button,分别调用IRegionManager.RegisterViewWithRegion方法向同一个Region(Region为ContentControl)注册View,但只有第一次可以,点击第二个按钮Region中就无法显示对应的View了,只显示第一个View。

     

    这两个问题困扰了我很久,不知道我哪里理解错了。

    2010年11月24日 9:50

答案

  • 你好,

    我个人觉得还是需要每一个View能够搭配一个ViewModel,这样,即使是嵌套的 View,比如一个View 要在另一个ViewRegion中显示,这个时候可以在ViewModel里面进行注册,还可以在当前ViewModel里面添加相应的 sub ViewModel 到ModelCatalog。 这样子会比较好的做到UI分离。

    还有,我测试了下不能注册的原因,是在于你使用了一个Border作为ViewRegion。把它换成ContentControl或者ItemsControl就好了 (建议是ItemsControl)!原因是:默认只映射了三种组件作为Region,看 \Desktop\Prism\PrismLibrary\Desktop\Prism\Bootstrapper.cs 的132行:

     regionAdapterMappings.RegisterMapping(typeof(Selector), ServiceLocator.Current.GetInstance<SelectorRegionAdapter>());
     regionAdapterMappings.RegisterMapping(typeof(ItemsControl), ServiceLocator.Current.GetInstance<ItemsControlRegionAdapter>());
     regionAdapterMappings.RegisterMapping(typeof(ContentControl), ServiceLocator.Current.GetInstance<ContentControlRegionAdapter>());
    

    而在你的应用里,也只指定了 Ribbon 和 Grid 作为Region容器,所以Border是无法注册的。你可以增加对Border的映射,或者是使用ItemsControl等已经有的映射!

    Bob Bao


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Are you looking for a typical code sample? Please download All in One Code Framework !

    如果有回复帮助并解决了您的问题,请点击 “标记为答复”,如果没有没有帮助,请随时点击“取消答复标记”
    你在为寻找代码示例而苦恼吗?赶快来下载 All in One Code Framework 微软一站式代码框架 吧!
    2010年11月29日 12:40
    版主
  • 你好 懵盛盛,

    关于第一个问题: 我按照你的说法写了一个测试项目, 在ViewA里面加了一个Region,并且建立了新的ViewC和ModelC。同时把ModalA和ModelC都添加到全局的 ModuleCatalog 里面,这样ViewC是可以注册到View1Region中, 并且运行时正常显示了ViewC。所以这个有可能是你没有在 ModuleCatalog  里面添加你的相应的ModelC。

    关于第二个问题,我研究了下 RegionManager ,发现他是用ViewCollection的一个集合来存储所有注册到这个Region的View的。然后通过一个过滤器,来选择所显示的当前View。当然,每一个Region有一个 ActiveViews 属性,还提供了一个 Activate 方法来设置一个 View 作为当前活动的View。我可以理解为什么许多Prsim的例子都是使用ItemsControl来展现一个View集合,如果你用到了ContentControl,下面的代码就可以来转换View:

     public DelegateCommand ViewACommand
     {
      get
      {
      return new DelegateCommand(new Action(() =>
      {
    
       object view = null;
       regionManager.RegisterViewWithRegion("subView", () =>
       {
       view = this.container.Resolve<Views.ViewA>();
       return view;
       });
       regionManager.Regions["subView"].Activate(view);
      }));
      }
     }
    
     public DelegateCommand ViewCCommand
     {
      get
      {
      return new DelegateCommand(new Action(() =>
      {
       object view = null;
       regionManager.RegisterViewWithRegion("subView", () =>
       {
       view = this.container.Resolve<Views.ViewC>();
       return view;
       });
       regionManager.Regions["subView"].Activate(view);
      }));
      }
     }
     
    

    我这里提供一个例子下载,是根据Prsim的HelloWorld修改的:http://cid-51b2fdd068799d15.office.live.com/self.aspx/.Public/Samples%5E_2010/20101126%5E_PrsimSwitchViews.zip

    致,

    Bob Bao


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Are you looking for a typical code sample? Please download All in One Code Framework !

    如果有回复帮助并解决了您的问题,请点击 “标记为答复”,如果没有没有帮助,请随时点击“取消答复标记”
    你在为寻找代码示例而苦恼吗?赶快来下载 All in One Code Framework 微软一站式代码框架 吧!

     

     

    非常感谢Bob Bao的解答!!

    第二个问题我已经通过RegionAdapter暂时解决了问题,暂时够用了。

    但是第一个问题依然困扰着我:

    我的情况比你的例子稍微复杂一些,请看链接中的DEMO。

    在Moudle中,我还不知道需要注册的View有哪些,所以我不能在Moudle的Init进行注册View。

    另外在动态添加的View中,我还希望能嵌套Region,以达成比较终极的UI分离,但View中的Region似乎不能注册。

    请看DEMO中的ModuleFunction中的Function2。Function2View中的TopRegion和ButtomRegion不能被注册到容器中。

    http://cid-7c49a2abb00e1af5.office.live.com/self.aspx/DEMO/MyVeryFristPrismProject.zip

    2010年11月28日 3:23

全部回复

  • 看一下

    http://www.cnblogs.com/Clingingboy/archive/2009/03/26/1422351.html 和

    http://www.cnblogs.com/Clingingboy/archive/2009/04/09/1432242.html

    希望对你有用,我也在学习中......

    谢谢你的回复,这两篇文章我都翻烂了,但是还是没能找到解决我问题的答案,郁闷
    2010年11月25日 3:26
  • 你好 懵盛盛,

    关于第一个问题: 我按照你的说法写了一个测试项目, 在ViewA里面加了一个Region,并且建立了新的ViewC和ModelC。同时把ModalA和ModelC都添加到全局的 ModuleCatalog 里面,这样ViewC是可以注册到View1Region中, 并且运行时正常显示了ViewC。所以这个有可能是你没有在 ModuleCatalog  里面添加你的相应的ModelC。

    关于第二个问题,我研究了下 RegionManager ,发现他是用ViewCollection的一个集合来存储所有注册到这个Region的View的。然后通过一个过滤器,来选择所显示的当前View。当然,每一个Region有一个 ActiveViews 属性,还提供了一个 Activate 方法来设置一个 View 作为当前活动的View。我可以理解为什么许多Prsim的例子都是使用ItemsControl来展现一个View集合,如果你用到了ContentControl,下面的代码就可以来转换View:

      public DelegateCommand ViewACommand
      {
       get
       {
        return new DelegateCommand(new Action(() =>
        {
    
         object view = null;
         regionManager.RegisterViewWithRegion("subView", () =>
         {
          view = this.container.Resolve<Views.ViewA>();
          return view;
         });
         regionManager.Regions["subView"].Activate(view);
        }));
       }
      }
    
      public DelegateCommand ViewCCommand
      {
       get
       {
        return new DelegateCommand(new Action(() =>
        {
         object view = null;
         regionManager.RegisterViewWithRegion("subView", () =>
         {
          view = this.container.Resolve<Views.ViewC>();
          return view;
         });
         regionManager.Regions["subView"].Activate(view);
        }));
       }
      }
     
    

    我这里提供一个例子下载,是根据Prsim的HelloWorld修改的:http://cid-51b2fdd068799d15.office.live.com/self.aspx/.Public/Samples%5E_2010/20101126%5E_PrsimSwitchViews.zip

    致,

    Bob Bao


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Are you looking for a typical code sample? Please download All in One Code Framework !

    如果有回复帮助并解决了您的问题,请点击 “标记为答复”,如果没有没有帮助,请随时点击“取消答复标记”
    你在为寻找代码示例而苦恼吗?赶快来下载 All in One Code Framework 微软一站式代码框架 吧!
    2010年11月26日 10:08
    版主
  • 你好 懵盛盛,

    关于第一个问题: 我按照你的说法写了一个测试项目, 在ViewA里面加了一个Region,并且建立了新的ViewC和ModelC。同时把ModalA和ModelC都添加到全局的 ModuleCatalog 里面,这样ViewC是可以注册到View1Region中, 并且运行时正常显示了ViewC。所以这个有可能是你没有在 ModuleCatalog  里面添加你的相应的ModelC。

    关于第二个问题,我研究了下 RegionManager ,发现他是用ViewCollection的一个集合来存储所有注册到这个Region的View的。然后通过一个过滤器,来选择所显示的当前View。当然,每一个Region有一个 ActiveViews 属性,还提供了一个 Activate 方法来设置一个 View 作为当前活动的View。我可以理解为什么许多Prsim的例子都是使用ItemsControl来展现一个View集合,如果你用到了ContentControl,下面的代码就可以来转换View:

     public DelegateCommand ViewACommand
     {
      get
      {
      return new DelegateCommand(new Action(() =>
      {
    
       object view = null;
       regionManager.RegisterViewWithRegion("subView", () =>
       {
       view = this.container.Resolve<Views.ViewA>();
       return view;
       });
       regionManager.Regions["subView"].Activate(view);
      }));
      }
     }
    
     public DelegateCommand ViewCCommand
     {
      get
      {
      return new DelegateCommand(new Action(() =>
      {
       object view = null;
       regionManager.RegisterViewWithRegion("subView", () =>
       {
       view = this.container.Resolve<Views.ViewC>();
       return view;
       });
       regionManager.Regions["subView"].Activate(view);
      }));
      }
     }
     
    

    我这里提供一个例子下载,是根据Prsim的HelloWorld修改的:http://cid-51b2fdd068799d15.office.live.com/self.aspx/.Public/Samples%5E_2010/20101126%5E_PrsimSwitchViews.zip

    致,

    Bob Bao


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Are you looking for a typical code sample? Please download All in One Code Framework !

    如果有回复帮助并解决了您的问题,请点击 “标记为答复”,如果没有没有帮助,请随时点击“取消答复标记”
    你在为寻找代码示例而苦恼吗?赶快来下载 All in One Code Framework 微软一站式代码框架 吧!

     

     

    非常感谢Bob Bao的解答!!

    第二个问题我已经通过RegionAdapter暂时解决了问题,暂时够用了。

    但是第一个问题依然困扰着我:

    我的情况比你的例子稍微复杂一些,请看链接中的DEMO。

    在Moudle中,我还不知道需要注册的View有哪些,所以我不能在Moudle的Init进行注册View。

    另外在动态添加的View中,我还希望能嵌套Region,以达成比较终极的UI分离,但View中的Region似乎不能注册。

    请看DEMO中的ModuleFunction中的Function2。Function2View中的TopRegion和ButtomRegion不能被注册到容器中。

    http://cid-7c49a2abb00e1af5.office.live.com/self.aspx/DEMO/MyVeryFristPrismProject.zip

    2010年11月28日 3:23
  • 你好,

    我个人觉得还是需要每一个View能够搭配一个ViewModel,这样,即使是嵌套的 View,比如一个View 要在另一个ViewRegion中显示,这个时候可以在ViewModel里面进行注册,还可以在当前ViewModel里面添加相应的 sub ViewModel 到ModelCatalog。 这样子会比较好的做到UI分离。

    还有,我测试了下不能注册的原因,是在于你使用了一个Border作为ViewRegion。把它换成ContentControl或者ItemsControl就好了 (建议是ItemsControl)!原因是:默认只映射了三种组件作为Region,看 \Desktop\Prism\PrismLibrary\Desktop\Prism\Bootstrapper.cs 的132行:

     regionAdapterMappings.RegisterMapping(typeof(Selector), ServiceLocator.Current.GetInstance<SelectorRegionAdapter>());
     regionAdapterMappings.RegisterMapping(typeof(ItemsControl), ServiceLocator.Current.GetInstance<ItemsControlRegionAdapter>());
     regionAdapterMappings.RegisterMapping(typeof(ContentControl), ServiceLocator.Current.GetInstance<ContentControlRegionAdapter>());
    

    而在你的应用里,也只指定了 Ribbon 和 Grid 作为Region容器,所以Border是无法注册的。你可以增加对Border的映射,或者是使用ItemsControl等已经有的映射!

    Bob Bao


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Are you looking for a typical code sample? Please download All in One Code Framework !

    如果有回复帮助并解决了您的问题,请点击 “标记为答复”,如果没有没有帮助,请随时点击“取消答复标记”
    你在为寻找代码示例而苦恼吗?赶快来下载 All in One Code Framework 微软一站式代码框架 吧!
    2010年11月29日 12:40
    版主
  • 你好,

    我个人觉得还是需要每一个View能够搭配一个ViewModel,这样,即使是嵌套的 View,比如一个View 要在另一个ViewRegion中显示,这个时候可以在ViewModel里面进行注册,还可以在当前ViewModel里面添加相应的 sub ViewModel 到ModelCatalog。 这样子会比较好的做到UI分离。

    还有,我测试了下不能注册的原因,是在于你使用了一个Border作为ViewRegion。把它换成ContentControl或者ItemsControl就好了 (建议是ItemsControl)!原因是:默认只映射了三种组件作为Region,看 \Desktop\Prism\PrismLibrary\Desktop\Prism\Bootstrapper.cs 的132行:

     regionAdapterMappings.RegisterMapping(typeof(Selector), ServiceLocator.Current.GetInstance<SelectorRegionAdapter>());
    
     regionAdapterMappings.RegisterMapping(typeof(ItemsControl), ServiceLocator.Current.GetInstance<ItemsControlRegionAdapter>());
    
     regionAdapterMappings.RegisterMapping(typeof(ContentControl), ServiceLocator.Current.GetInstance<ContentControlRegionAdapter>());
    
    

    而在你的应用里,也只指定了 Ribbon 和 Grid 作为Region容器,所以Border是无法注册的。你可以增加对Border的映射,或者是使用ItemsControl等已经有的映射!

    Bob Bao


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Are you looking for a typical code sample? Please download All in One Code Framework !

    如果有回复帮助并解决了您的问题,请点击 “标记为答复”,如果没有没有帮助,请随时点击“取消答复标记”
    你在为寻找代码示例而苦恼吗?赶快来下载 All in One Code Framework 微软一站式代码框架 吧!


    再次多谢Bob Bao的回答!

    的确是我被ContentControl的继承关系搞糊涂了,以为Border是子类,自然可以把ContentControl的Adapter继承过来。实在是自己抽风了。

    我已经在尽力在项目里推行MVVM,只在DEMO里写一些CodeBehind的代码。

     

    请Bob Bao再帮我看看以下问题:

    在链接的项目(PrismViewContainRegion)中还是View嵌套Region,可以正常显示,但是当点击按钮第三次时,Prism的RegionManager中报出异常“Region with the given name is already registered”。

     我看了下Prism的源码,估计是RegionBehavior没设置好,但是Prism的文档没有这方面的详细介绍,不知道改如何修改?

    需求如下:

    点击Tab中的按钮,可在MainRegion打开ViewA(ViewA可包含多个Region),再次点击按钮,可在MainRegion中打开新的ViewA实例,旧有ViewA实例可保存在程序内,以供随时再插入到MainRegion中。

    DEMO源码地址:http://cid-7c49a2abb00e1af5.skydrive.live.com/redir.aspx?resid=7C49A2ABB00E1AF5!2706

    2010年12月1日 7:06
  • 你好 懵盛盛,

    由于你最初的问题已经基本得到了解决,所以我先将解决了您最初问题的回复标记为"答案", 当然,我会继续跟进您的新问题的,请不要担心,我们会进行研究来给与你一个满意的答复的!

    谢谢你对我们工作的支持!

    Bob Bao


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Are you looking for a typical code sample? Please download All in One Code Framework !

    如果有回复帮助并解决了您的问题,请点击 “标记为答复”,如果没有没有帮助,请随时点击“取消答复标记”
    你在为寻找代码示例而苦恼吗?赶快来下载 All in One Code Framework 微软一站式代码框架 吧!
    2010年12月2日 9:14
    版主
  • 你好,

    我跟了你的代码,当我们每次去使用一个新的 RegionManager 的时候,就不会发生一个View被多次注册了。

    regionManager.Regions["MainRegion"].Add(mainView, viewname ,true);

    但是如果你想持久化一个View的话,还是建议你自己来维护这个View的状态,并且在更换当前View的时候来写一些逻辑去防止一个View被多次的注册到一个Region上.

    关于Prsim的文档你可以访问:http://msdn.microsoft.com/en-us/library/gg406140.aspx 或者下载离线的文档:http://compositewpf.codeplex.com/releases/view/55580

    Bob Bao


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Are you looking for a typical code sample? Please download All in One Code Framework !

    如果有回复帮助并解决了您的问题,请点击 “标记为答复”,如果没有没有帮助,请随时点击“取消答复标记”
    你在为寻找代码示例而苦恼吗?赶快来下载 All in One Code Framework 微软一站式代码框架 吧!
    2010年12月3日 17:20
    版主
  • 你好,

    我跟了你的代码,当我们每次去使用一个新的 RegionManager 的时候,就不会发生一个View被多次注册了。

    regionManager.Regions["MainRegion"].Add(mainView, viewname ,true);

    但是如果你想持久化一个View的话,还是建议你自己来维护这个View的状态,并且在更换当前View的时候来写一些逻辑去防止一个View被多次的注册到一个Region上.

    关于Prsim的文档你可以访问:http://msdn.microsoft.com/en-us/library/gg406140.aspx 或者下载离线的文档:http://compositewpf.codeplex.com/releases/view/55580

    Bob Bao


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Are you looking for a typical code sample? Please download All in One Code Framework !

    如果有回复帮助并解决了您的问题,请点击 “标记为答复”,如果没有没有帮助,请随时点击“取消答复标记”
    你在为寻找代码示例而苦恼吗?赶快来下载 All in One Code Framework 微软一站式代码框架 吧!


    非常感谢Bob Bao的解答!!

    你的回答给了我很多很好的思路!

    虽然以下的代码有点笨,但是似乎解决了当前的问题:

    var oldView = regionManager.Regions["MainRegion"].GetView("mainView");
    
    if (oldView!=null)
    {
      regionManager.Regions["MainRegion"].Remove(oldView);
    }
      MainView mainView = container.Resolve<MainView>();
      regionManager.Regions["MainRegion"].Add(mainView, "mainView", true);
    

    Prism是一个不错的UI模块化解决方案,但是在更复杂的应用中,要解决的疑难杂症也越多了。

    再次感谢Bob Bao的不懈坚持解答我的问题! 

    2010年12月4日 16:24