Loading

从PRISM开始学WPF(三)Prism-Region-更新至Prism7.1

[7.1update]在开始前,我们先看下版本7.1中在本实例中的改动。

  1. 首先,项目文件中没有了Bootstrapper.cs,在上一篇的开始,我们说过了,在7.1中,不见推荐使用Bootstrapper,相关改动整合到app.xaml和app.xaml.cs中。
  2. 然后: app.xaml
<prism:PrismApplication x:Class="Regions.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:prism="http://prismlibrary.com/"
             xmlns:local="clr-namespace:Regions">
    <Application.Resources>
         
    </Application.Resources>
</prism:PrismApplication>

在6.x中,这里还是一个Application,现在已经改成prism:PrismApplication
然后是,App.xaml.cs

using Prism.Ioc;
using Prism.Unity;
using Regions.Views;
using System.Windows;

namespace Regions
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : PrismApplication
    {
        protected override Window CreateShell()
        {
            return Container.Resolve<MainWindow>();
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            
        }
    }
}

这里用了 Prism.IocPrism.Unity
新的Prism.IoC命名空间,它创建了一个依赖注入容器的抽象。您现在只使用Prism提供的IContainerRegistry和IContainerProvider接口,而不是直接使用容器类。该IContainerProvider 接口用于从容器解析服务,IContainerRegistry 用于与容器登记类型。
而之前的Unity也不再使用了,现在使用Prism.Unity,上面App.xaml.cs代码中 的PrismApplication 正是存在于Prism.Unity,如果你需要从6.x升级到7.x,所有的unity引用都需要删掉,重新添加Prism.Unity,并且修改相关代码。

0x3 Region

regions

Regions是应用程序UI的逻辑区域,它很像一个PlaceHolder,Views在Regions中展现,很多种控件可以被用作Region :ContentControl、ItemsControl、ListBox、TabControl。

简单的说,就是一个容器(区域适配器),用来装载Views的。这像WinForms中的Container控件Panel,里面可以放置其他控件。在PRISM中,Views也是用户控件(UserControl

Region的注册方式:

​ 在MainWindow.xaml中:

<Window x:Class="Regions.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        Title="Shell" Height="350" Width="525">
    <Grid>
        <ContentControl prism:RegionManager.RegionName="ContentRegion" />
    </Grid>
</Window>

从这里开始,我们就不得不面对 XAML了。继续引用维基百科的介绍:

XAML(Extensible Application Markup Language)是Windows Presentation Foundation(WPF)的一部分,是微软开发的一种基于XML、基于声明,用于初始化结构化值和对象的用户界面描述语言,它有着HTML的外观,又揉合了XML语法的本质,例如:可以使用<Button>标签设置按钮Button

(⊙﹏⊙)。。。

好,这个很简单,不需要介绍了。然后我们看代码,首先在头部引入命名空间xmlns:prism="http://prismlibrary.com/",这个prism是别名,你也可以像上面的x一样将他命名成其他你想要的名字比如sm 😏,当然了我们默认使用prism这样比较符合命名规范,然后在Grid控件里面,新建了了一个ContentControl,作为Region的目标,并且给他取了一个名字ContentRegion

由于更新7.1导致篇幅过长,这里将控件定制region单独摘了一篇:
是不是所有的控件都可以用来做Region呢?

注册视图

指定了Region,接下来就为Region指定View了。

在Views目录下面,新建一个UserControl,并在Grid控件内,加一个TextBlock,写上字,标识这是View A。

依旧省去了大部分头部引用,代码都是在Prism-Samples-Wpf里的,这里贴出来仅方便大家无源码阅读

<UserControl x:Class="ViewDiscovery.Views.ViewA"
			...
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <TextBlock Text="View A" FontSize="38" />
    </Grid>
</UserControl>

我们现在想要,在上一小节制定的Region内显示View A,怎么做呢?我们来看MainWindow的code-behind,即:MainWindow.xaml.cs

using Prism.Regions;
using System.Windows;

namespace ViewDiscovery.Views
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow(IRegionManager regionManager)
        {
            InitializeComponent();
            //view discovery
            regionManager.RegisterViewWithRegion("ContentRegion", typeof(ViewA));
        }
    }
}

看上去,他只用了一行代码就实现了,在Region中显示ViewA。可仔细看一下,这好像哪不太一样。最早我们的MainWindow.xaml.cs的构造函数是没有参数的,这里多了一个IRegionManager类型的参数regionManager,是不是很眼熟?

依赖注入容器

[7.1updated]虽然7.1不再使用Unity,但这不影响我们来了解依赖注入容器在prism中的作用
prism是使用依赖注入容器实现依赖注入的,这里我们使用的是Unity,Prism同样支持Mef容器实现依赖注入。[7.1updated]现已不再支持Mef容器了

如果使用 Unity 实例化一个类,该类的构造函数依赖一个或多个其他类,则 Unity 会为构造函数自动创建参数中指定的被依赖的类的实例。上面MainWindow的构造函数中的regionManager参数,就是Unity自动创建的。

参考:IoC 依赖注入容器 Unity

RegionManager

代码中RegionManager的RegisterViewWithRegion方法将我们的视图(View)和区域适配器(Region)进行关联

RegionManager,它实现了IRegionManager接口。IRegionManager接口包含一个只读属性Regions,是Region的集合(这个集合是从xaml中获取的,也就是我们定义的那些),RegionManager的实例会使用他们,并将view注册给他们。

View Discovery和View Injection

在Prism中有两种方式来定义视图与Region之间的映射关系——View DiscoveryView Injection

上面的regionManager.RegisterViewWithRegion("ContentRegion", typeof(ViewA));就是View Discovery

然后我们看一下View Injection

using Prism.Ioc;
using Prism.Regions;
using System.Windows;

namespace ViewInjection.Views
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        IContainerExtension _container;
        IRegionManager _regionManager;

        public MainWindow(IContainerExtension container, IRegionManager regionManager)
        {
            InitializeComponent();
            _container = container;
            _regionManager = regionManager;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var view = _container.Resolve<ViewA>();
            IRegion region = _regionManager.Regions["ContentRegion"];
            region.Add(view);
        }
    }
}

他从_regionManager中获取Region,然后使用IRegion.Add(View)的方式来向已有的Region中添加View。

视图的激活与取消激活

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            //activate view a
            _region.Activate(_viewA);
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            //deactivate view a
            _region.Deactivate(_viewA);
        }
posted @ 2018-04-02 16:31  可是我爱你啊  阅读(13069)  评论(9编辑  收藏  举报