• Prism V2之旅(3)


        上篇介绍了Region的基本应用,这篇接上篇,继续介绍关于Region的相关应用—RegionAdapter

        示例代码下载

    1.预先实现映射关系RegionAdapterMappings

    RegionAdapterMappings对Control和RegionAdapter做了一个映射,这个映射是在Bootstrapper引导程序中完成的.

            protected virtual RegionAdapterMappings ConfigureRegionAdapterMappings()
            {
                RegionAdapterMappings regionAdapterMappings = Container.TryResolve<RegionAdapterMappings>();
                if (regionAdapterMappings != null)
                {
                    regionAdapterMappings.RegisterMapping(typeof(Selector), this.Container.Resolve<SelectorRegionAdapter>());
                    regionAdapterMappings.RegisterMapping(typeof(ItemsControl), this.Container.Resolve<ItemsControlRegionAdapter>());
                    regionAdapterMappings.RegisterMapping(typeof(ContentControl), this.Container.Resolve<ContentControlRegionAdapter>());
                }
    
                return regionAdapterMappings;
            }

    这里提供了三种控件支持,在上篇也有交代.RegionAdapter必须实现IRegionAdapter接口

    2.在注册Region时寻找RegionAdapter

    <StackPanel cal:RegionManager.RegionName="MainRegion"/>

    以上的定义是错误的,因为在RegionAdapterMappings无法找到StackPanel和RegionAdapter的映射关系.以上附加属性的设置会尝试执行以下代码

    protected virtual IRegion CreateRegion(DependencyObject targetElement, string regionName)
    {
        // Build the region
        IRegionAdapter regionAdapter = this.regionAdapterMappings.GetMapping(targetElement.GetType());
        IRegion region = regionAdapter.Initialize(targetElement, regionName);
    
        return region;
    }

    为了支持StackPanel,我们可以尝试为StackPanel定义一个实现IRegionAdapter的区域适配器.

    3.自定义RegionAdapter

    以下为StackPanel定义RegionAdapter为例子

    3.1.定义一个实现IRegionAdapter的适配器,在这里可以控制StackPanel对象

    public class StackPanelRegionAdapter : IRegionAdapter
    {
        public IRegion Initialize(object regionTarget, string regionName)
        {
            StackPanel panel = regionTarget as StackPanel;
            panel.Children.Add(new Label() { Content = "hello" });
            return new Region();
        }
    }

    3.2 重写Bootstrapper的ConfigureRegionAdapterMappings方法,注册映射关系

    protected override RegionAdapterMappings ConfigureRegionAdapterMappings()
    {
        RegionAdapterMappings regionAdapterMappings = base.ConfigureRegionAdapterMappings();
        regionAdapterMappings.RegisterMapping(typeof(StackPanel), this.Container.Resolve<StackPanelRegionAdapter>());
        return regionAdapterMappings;
    }

     

    现在就可以在StackPanel注册Region了

    <StackPanel cal:RegionManager.RegionName="MainRegion"/>

    4.根据Region的操作变更UI

    我们来看一下IRegion接口

    image

    关于Region的基本应用在上篇已经介绍,主要用于对View的一些操作,之后ActiveViews和Views集合会发生变化,这两个集合是IViewsCollection类型并支持INotifyCollectionChanged接口.控件可以根据IRegion的信息变更做出变更.

    以上StackPanelRegionAdapter重构后如下,看到这里再回头看上篇就能更好的理解Activate这些方法的作用了.

    public class StackPanelRegionAdapter : IRegionAdapter
    {
        public IRegion Initialize(object regionTarget, string regionName)
        {
            StackPanel panel = regionTarget as StackPanel;
            AllActiveRegion region = new AllActiveRegion();
            region.Name = regionName;
            region.ActiveViews.CollectionChanged += delegate
            {
                panel.Children.Clear();
                foreach (var item in region.ActiveViews)
                {
                    panel.Children.Add(item as UIElement);
                }
            };
            return region;
        }
    }

    请注意,以上代码还无法执行虽然完成了适配,但当注册Region以后,还需要将Region添加到RegionManager中,我们还需要做一些额外的操作.prism提供内置的RegionAdapterBase抽象类,实现了IRegionAdapter,帮助我们做了一些额外的工作.我们可以从这个抽象类继承.

    我们来看RegionAdapterBase实现的Initialize方法,给我们制定了模板,我们就重写这些方法就可以了

    public IRegion Initialize(T regionTarget, string regionName)
    {
        if (regionName == null)
            throw new ArgumentNullException("regionName");
    
        IRegion region = CreateRegion();
        region.Name = regionName;
    
        SetObservableRegionOnHostingControl(region, regionTarget);
    
        Adapt(region, regionTarget);
        AttachBehaviors(region, regionTarget);
        AttachDefaultBehaviors(region, regionTarget);
        return region;
    }

    一般情况下我们只需要重写Adapt和CreateRegion即可.先重构如下

    public class StackPanelRegionAdapter : RegionAdapterBase<StackPanel>
    {
    
        public StackPanelRegionAdapter(IRegionBehaviorFactory defaultBehaviors)
            : base(defaultBehaviors)
        {
        }
    
        protected override void Adapt(IRegion region, StackPanel regionTarget)
        {
            region.ActiveViews.CollectionChanged += delegate
            {
                regionTarget.Children.Clear();
                foreach (var item in region.ActiveViews)
                {
                    regionTarget.Children.Add(item as UIElement);
                }
            };
        }
    
        protected override IRegion CreateRegion()
        {
            return new AllActiveRegion();
        }
    }

     

    内置实现IRegion有三个类型,如ContentControl并不是一个集合控件,则会创建一个SingelActiveRegion,集合控件则创建AllActiveRegion

    image

    在RegionAdapter中出现了RegionBehavior,将在下篇介绍此应用.下图解释了以上执行过程.

    image

  • 相关阅读:
    Ubuntu下下载Android源码
    升级Android 3.1ADT 和SDK
    ubuntu10.04手动安装jdk1.6.0_24配置
    安装VM Tools
    Singleton (单件模式)
    biztalk2004安装时应该注意的几点
    欢迎高手加入.NET技术群
    Observer(观察者模式)
    无眠
    A⑤权限管理分配权限:提交的是节点的id列表
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/prism_part3.html
Copyright © 2020-2023  润新知