zoukankan      html  css  js  c++  java
  • Prism V2之旅(2)

         本篇将介绍Prism中Region的使用.

     本篇Demo下载

    在这里我们统一prism里面一些名字的称谓.

    1.Shell 主程序容器

    2.Region 内容区域

    3.Module 模块

    4.wpf 不是特殊情况,就是指wpf和silverlight

    一.wpf的内容控件

        继承自ContentControl控件的,我们称之为内容控件.

    <ContentControl Content=""></ContentControl>

    ContentControl控件定义了一个Content,在没有框架的情况下,也可以将其作为一个内容区域.然而为了满足ui的需求,我们还需要各种不同的控件来当内容区域,如TabControl,DockPanel,Selector等。有些控件则继承自ItemsControl属于集合控件,不属于内容控件.但他们根据不同需求,同时都可以当容器使用,但他们的使用方式却不同.

    为了统一对内容区域的操作,prism提供了一种适配模式,也可以说提供了控件与Region的映射关系.将不同可以作为容器的控件的操作方式统一为Region的操作方式.

    prism内置有三种控件可以作为内容区域适配对象

    1. ContentControl
    2. ItemsControl
    3. Selector

    看起来只有三个,但是只要是继承自这三个控件的其他控件也可以.下面介绍使用方法.

    二.Region的基本操作,以下以Hello World为示例

    1.在Shell中注册内容区域

    如下代码,http://www.codeplex.com/CompositeWPF是prism注册的命名空间.

    RegionManager的附加属性RegionName注册了一个名叫MainRegion的内容区域

    <Window x:Class="HelloWorldSample.Shell"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:cal="http://www.codeplex.com/CompositeWPF"
        Title="Composite Application Library Sample" Width="400" Height="300">
        <ContentControl cal:RegionManager.RegionName="MainRegion"/>
    </Window>

    2.通过IRegionManager获取已注册的内容区域

    已注册的Region将保存在IRegionManager的Regions集合里面,根据注册的名字取出Region,将返回一个IRegion对象.

    IRegion mainRegion = this.regionManager.Regions["MainRegion"];

    3.在Region中添加内容

    首先定义一个用户控件

    <UserControl x:Class="HelloWorld.Views.HelloWorldView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Grid>
            <TextBlock Text="Hello World" Foreground="Green" 
                       HorizontalAlignment="Center" VerticalAlignment="Center" 
                       FontFamily="Calibri" FontSize="24" FontWeight="Bold"></TextBlock>
        </Grid>
    </UserControl>

    通过IRegion的Add方法添加用户控件.以下是一个简单模块的完成代码,当这个模块加载时,会默认执行Initialize方法.

    public class HelloWorldModule : IModule
    {
        private readonly IRegionManager regionManager;
    
        public IUnityContainer container { get; set; }
    
        public HelloWorldModule(IRegionManager regionManager, IUnityContainer container)
        {
            this.regionManager = regionManager;
            this.container = container;
        }
    
        public void Initialize()
        {
            RenderHelloWorldView(); 
        }
    
        void RenderHelloWorldView()
        {
            IRegion mainRegion = this.regionManager.Regions["MainRegion"];
            mainRegion.Add(new HelloWorldView());
        }
    }

    下图表达以上三个步骤的意思.

    image

    三.Region对View的操作

    1.可以将以下操作并为一类.Add方法有三个重载,第三个方法下面再解释.当给View指定一个名字时,可以通过GetView方法获取View,然后通过Remove方法删除.

            IRegionManager Add(object view);
            IRegionManager Add(object view, string viewName);
            IRegionManager Add(object view, string viewName, bool    
                               createRegionManagerScope);
            void Remove(object view);
            object GetView(string viewName); 
    
    2.激活和停用View
    默认情况下,当一个View添加到Region当中,都被记做是处于活动状态。IRegion提供了2个集合和2个方法来控制View的活动状态.Activate方法将View转为可活动状态,Deactivate方法则冻结了View的使用.两个方法的调用将使Views和ActiveViews两个集合属性发生变化.IViewsCollection实现了INotifyCollectionChanged接口了,所以当集合发生变化时会触发一个事件来引发ui界面发生变化,这个事件的引发由Region和控件的适配器来完成.如何自定义RegionAdapter将在下次介绍,回头再看到这里就非常清楚了.
     
            IViewsCollection Views { get; }
            IViewsCollection ActiveViews { get; }
            void Activate(object view);
            void Deactivate(object view);   
    
    

    四.注册子区域Region

    1.在Region中添加的View同时也可以注册Region的,但这个被添加的View必须依靠依赖注入的功能才可以.请看以下示例

    <UserControl x:Class="HelloWorld.Views.HelloWorldViewAgain"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:cal="http://www.codeplex.com/CompositeWPF"
        Height="300" Width="300">
        <Grid>
            <StackPanel>
                <TextBlock Text="HelloWorldViewAgain"></TextBlock>
                <TextBlock Text="HelloWorldView Loading"></TextBlock>
                <ItemsControl cal:RegionManager.RegionName="HelloWorldViewAgain"/>
                <TextBlock Text="HelloWorldView Loaded"></TextBlock>
            </StackPanel>
        </Grid>
    </UserControl>
    

    在Shell的Region中添加HelloWorldViewAgain

    void RenderHelloWorldViewAgain()
    {
        IRegion mainRegion = this.regionManager.Regions["MainRegion"];
        HelloWorldViewAgain viewAgain = container.Resolve<HelloWorldViewAgain>();
        mainRegion.Add(viewAgain, "MainRegion");
        viewAgain.DisplayHelloWorldView();
    }

    DisplayHelloWorldView方法则在定义的HelloWorldViewAgain的Region添加了HelloWorldView

    public void DisplayHelloWorldView()
    {
        IRegion secondRegion = this.regionManager.Regions["HelloWorldViewAgain"];
        secondRegion.Add(new HelloWorldView());
    }

    下图表达了以上步骤的意思

    image

    2.设定RegionManager的管理范围

    默认情况下,当注册一个Region的时候,RegionManager会将其加入到其Regions集合当中.

    <ContentControl  x:Name=”panel” cal:RegionManager.RegionName="MainRegion"/>

    这个Regions属性属于ContentControl的附加属性,可以通过RegionManager的GetRegionManager方法获取该控件的Region集合.

    回头再看上面的一个Add方法.

    IRegionManager Add(object view, string viewName, bool createRegionManagerScope);

    在添加Region中添加一个View的时候,你可以指定是否重新设定RegionManager的范围.如果设置为True的话,将会调用CreateRegionManager方法为当前的View重新创建一个RegionManager.这就说明了如果创建的View中注册了一个Region,改Region是不知道其存在哪个RegionManager里面的.

    现在我们重新更改上面的RenderHelloWorldViewAgain方法,添加View时,

    第三个参数设置为True,如下

    void RenderHelloWorldViewAgain()
    {
        IRegion mainRegion = this.regionManager.Regions["MainRegion"];
        HelloWorldViewAgain viewAgain = container.Resolve<HelloWorldViewAgain>();
        mainRegion.Add(viewAgain, "HelloWorldViewAgain",true);
        viewAgain.DisplayHelloWorldView();
    }

    这时HelloWorldViewAgain这个View已注册的Region,就很难知道其在哪个RegionManager,现在DisplayHelloWorldView方法更改如下

    public void DisplayHelloWorldView()
    {
        var view=this.regionManager.Regions["MainRegion"].GetView("HelloWorldViewAgain") as DependencyObject;
        IRegion region=RegionManager.GetRegionManager(view).Regions["HelloWorldViewAgain"];
        region.Add(new HelloWorldView(), "hello");
    }

    这种做法虽然可以避免Region重名等一些问题,但为获取Region的RegionManager也有一些麻烦.

    这篇主要介绍了Region的一些基本功能,下篇将继续讨论.

  • 相关阅读:
    [LeetCode]230. 二叉搜索树中第K小的元素(BST)(中序遍历)、530. 二叉搜索树的最小绝对差(BST)(中序遍历)
    【二叉树-所有路经系列(根->叶子)】二叉树的所有路径、路径总和 II、路径总和、求根到叶子节点数字之和(DFS)
    [LeetCode]1083. 销售分析 II(Mysql,having+if)
    [LeetCode]196. 删除重复的电子邮箱(delete)
    [LeetCode]面试题62. 圆圈中最后剩下的数字(数学)
    [算法]十进制整数转八进制
    [LeetCode]534. 游戏玩法分析 III(Mysql)
    [LeetCode]Mysql小本本
    [LeetCode]Mysql系列5
    Java 冒泡排序的实现
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/prism_part2.html
Copyright © 2011-2022 走看看