添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

WPF Prism(一)Region
WPF Prism(二)Module
WPF Prism(三)ViewModelLocator
WPF Prism(四)MVVM
WPF Prism(五)Navigation
WPF Prism(六)Dialog

一、什么是Region

在Prism当中,一个页面我们可以不再为其固定显示的内容,而这种概念变成了区域(Region)划分的概念。将页面显示的区域划分成N个Region,每一个Region将动态分配区域。它将负责承担我们的UI组件或者控件。

二、RegionManager类

  • 维护区域集合
  • 提供对区域的访问
  • 合成视图
  • 区域导航
  • 定义区域

三、使用RegionManager

首先,我们需要将MainWindow的构造函数传入IRegionManager参数:

    public partial class MainWindow : Window
        public MainWindow(IRegionManager regionManager)
            InitializeComponent();

注意:因为MainWindow对象是我们在App类中使用容器解析得到的,那么它需要的依赖IRegion也会自动被创建,不需要我们自己创建。

在定义视图与Region之间的映射关系之前我们需要先定义Region,定义Region有两种方法:

3.1、在xaml中

<Window
    xmlns:prism="http://prismlibrary.com/"
    Title="Shell">
        <Grid.RowDefinitions>
            <RowDefinition Height="0.2*" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <ContentControl Grid.Row="0" prism:RegionManager.RegionName="HeaderRegion" />
    </Grid>
</Window>

代码有省略,重点关注需要引入prism命名空间。

3.2、在cs文件中

<ContentControl x:Name="Header" Grid.Row="0" />
        public MainWindow(IRegionManager regionManager)
            InitializeComponent();
            RegionManager.SetRegionName(Header, "HeaderRegion");

上述两种方式都是可以的。

四、View Discovery和View Injection

现在我们在MainWindow中定义了三个Region,同时定义了三个UserControl。

<Window
    x:Class="PrismBlankAppCore.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"
    Width="525"
    Height="350">
        <Grid.RowDefinitions>
            <RowDefinition Height="0.2*" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <ContentControl Grid.Row="0" prism:RegionManager.RegionName="HeaderRegion" />
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="0.4*" />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <ContentControl Grid.Column="0" prism:RegionManager.RegionName="MenuRegion" />
            <ContentControl Grid.Column="1" prism:RegionManager.RegionName="ContentRegion" />
        </Grid>
    </Grid>
</Window>

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

4.1View Discovery

        public MainWindow(IRegionManager regionManager)
            InitializeComponent();
            //View Dicovery
            regionManager.RegisterViewWithRegion("HeaderRegion", typeof(HeaderView));
            regionManager.RegisterViewWithRegion("MenuRegion", typeof(MenuView));
            regionManager.RegisterViewWithRegion("ContentRegion", typeof(ContentView));

4.2View Injection

    public partial class MainWindow : Window
        private IRegionManager regionManager;
        private IContainerExtension container;
        public MainWindow(IRegionManager regionManager, IContainerExtension container)
            InitializeComponent();
            //View Dicovery
            //regionManager.RegisterViewWithRegion("HeaderRegion", typeof(HeaderView));
            //regionManager.RegisterViewWithRegion("MenuRegion", typeof(MenuView));
            //regionManager.RegisterViewWithRegion("ContentRegion", typeof(ContentView));
            this.regionManager = regionManager;
            this.container = container;
        private void Window_Loaded(object sender, RoutedEventArgs e)
            //View Injection
            HeaderView headerView = container.Resolve<HeaderView>();
            regionManager.Regions["HeaderRegion"].Add(headerView);
            MenuView menuView = container.Resolve<MenuView>();
            regionManager.Regions["MenuRegion"].Add(menuView);
            ContentView contentView = container.Resolve<ContentView>();
            regionManager.Regions["ContentRegion"].Add(contentView);

注入View的时候需要用到Add方法,还得提前将View对象创建好,所以在构造函数中我们需要注入IRegionManager和IContainerExtension的实现。

值得一提的是,在构造函数中IRegionManager对象还没有创建完成(应该是RegionName还没有创建完成),所以在Load函数中完成View Injection。如果需要View对象是单例的,可以提前在App类的重写函数中注册单例对象。

4.3Active和Deactivate

将App类修改为:View对象注册为单例对象。

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
            containerRegistry.RegisterSingleton<HeaderView>();
            containerRegistry.RegisterSingleton<MenuView>();
            containerRegistry.RegisterSingleton<ContentView>();

MainWindow增加了三个按钮:

        <UniformGrid Grid.Row="2" Columns="3">
            <Button
                Width="80"
                Height="30"
                Content="Activate" Click="Activate"/>
            <Button
                Width="80"
                Height="30"
                Content="Refresh" Click="Refresh" />
            <Button
                Width="80"
                Height="30"
                Content="Deactivate" Click="Deactivate
        </UniformGrid>

增加对应的三个方法:

    private void Activate(object sender, RoutedEventArgs e)
        HeaderView headerView = container.Resolve<HeaderView>();
        regionManager.Regions["HeaderRegion"].Activate(headerView);
        MenuView menuView = container.Resolve<MenuView>();
        regionManager.Regions["MenuRegion"].Activate(menuView);
        ContentView contentView = container.Resolve<ContentView>();
        regionManager.Regions["ContentRegion"].Activate(contentView);
    private void Refresh(object sender, RoutedEventArgs e)
        //刷新  因为已经add过,所以需要先remove
        HeaderView headerView = container.Resolve<HeaderView>();
        regionManager.Regions["HeaderRegion"].Remove(headerView);
        MenuView menuView = container.Resolve<MenuView>();
        regionManager.Regions["MenuRegion"].Remove(menuView);
        ContentView contentView = container.Resolve<ContentView>();
        regionManager.Regions["ContentRegion"].Remove(contentView);
        regionManager.Regions["HeaderRegion"].Add(headerView);
        regionManager.Regions["MenuRegion"].Add(menuView);
        regionManager.Regions["ContentRegion"].Add(contentView);
    private void Deactivate(object sender, RoutedEventArgs e)
        //使无效
        HeaderView headerView = container.Resolve<HeaderView>();
        regionManager.Regions["HeaderRegion"].Deactivate(headerView);
        MenuView menuView = container.Resolve<MenuView>();
        regionManager.Regions["MenuRegion"].Deactivate(menuView);
        ContentView contentView = container.Resolve<ContentView>();
        regionManager.Regions["ContentRegion"].Deactivate(contentView);

五、RegionAdapters

Prism提供了许多内置得RegionAdapter:

  • ContentControlRegionAdapter
  • ItemsControlRegionAdapter
  • SelectorRegionAdapter
    - ComboBox
    - ListBox
    - Ribbon
    - TabControl

除此之外,如果想要实现控件作用域Region,则必须创建自定义RegionAdapter。

下面我们创建一个一个基于StackPanel的自定义适配器。

5.1首先从创建一个继承于RegionAdapterBase的类。

    public class StackPanelRegionAdapter : RegionAdapterBase<StackPanel>
        public StackPanelRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory) : base(regionBehaviorFactory)
        protected override void Adapt(IRegion region, StackPanel regionTarget)
            throw new System.NotImplementedException();
        protected override IRegion CreateRegion()
            throw new System.NotImplementedException();

5.2实现重写的方法

public class StackPanelRegionAdapter : RegionAdapterBase<StackPanel>
    public StackPanelRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory) : base(regionBehaviorFactory)
    protected override void Adapt(IRegion region, StackPanel regionTarget)
        region.Views.CollectionChanged += (s, e) =>
            if (e.Action == NotifyCollectionChangedAction.Add)
                foreach (FrameworkElement element in e.NewItems)
                    regionTarget.Children.Add(element);
            else if (e.Action == NotifyCollectionChangedAction.Remove)
                foreach (FrameworkElement element in e.OldItems)
                    regionTarget.Children.Remove(element);
            //handle other case
    protected override IRegion CreateRegion()
        return new Region();

5.3最后需要在App类中注册适配器

        protected override void ConfigureRegionAdapterMappings(RegionAdapterMappings regionAdapterMappings)
            base.ConfigureRegionAdapterMappings(regionAdapterMappings);
            regionAdapterMappings.RegisterMapping(typeof(StackPanel), Container.Resolve<StackPanelRegionAdapter>());
                                    1. 什么是Prism
        Prism是一个用于在 WPF、Xamarin Form、Uno 平台和 WinUI 中构建松散耦合、可维护和可测试的 XAML 应用程序框架。
        Prism是一个用于在WPF、Xamarin Forms、Uno Platform和WinUI中构建松耦合、可维护和可测试的XAML应用程序的框架。 
                                    一、什么是Prism
Prism是一个用于在 WPF、Xamarin Form、Uno 平台和 WinUI 中构建松散耦合、可维护和可测试的 XAML 应用程序框架。
二、官方地址
https://github.com/PrismLibrary/Prism
基于Prism的VisualStudio扩展包模板: Prism Template Pack,下载它后可以快速创建基于Prism的项目。
三、Prism框架内容
框架中包括 MVVM、依赖注入、Command、Message Event、导航、弹窗等功能
这时候会报错,我们去修改前台的代码
<prism:PrismApplication x:Class="PrisimDemo.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presen
                                    Region定义
1、Xaml方式注册一个区域
<ContentControl x:Name="cc" prism:RegionManager.RegionName="ContentRegion"/>
2、后台代码注册一个区域
        public MainWindow(IRegionManager regionManager)
            InitializeComponent();
            RegionManager.SetRegio
                                    在实际应用开发中,随着项目业务逐渐复杂,耦合度会越来越高,维护成本也会直线上升,所以解耦也变得越来越重要。Prism框架为WPF开发中解耦提供了非常便捷的应用。今天主要以一个简单的小例子,简述WPF开发中Prism框架的简单应用,如有不足之处,还请指正。
什么是PrismPrism是一个开源框架,用于在WPF、Xamarin Forms、Uno/Win UI等应用中创建松耦合、可维护、可测试的XAML应用程序。Prism提供了一组设计模式的实现,这些设计模式有助于编写结构良好且可维护的XAML应用程
                                    在之前的文章中,为了能在MVVM框架中为前端View提供逻辑/数据绑定支持,使得后端数据具备通知UI数据变更的能力,我们手动实现了INotifyPropertyChanged 接口并将其封装为 **ViewModelBase** 基类。在Prism框架中,Prism扩充了WPF的绑定通知功能。提供了已经实现INotifyPropertyChanged接口并封装好的基类 **BindableBase** 。并使用 CallerMemberName 特性自动获取属性名称,解决了属性改变事件调用繁琐的问题,同
                                    融合官方文档和个人理解并参考其他博主的相关文章,对prism框架下的各个功能模块进行了较为详细的整理,并通过案例代码的方式更加直观的呈现相关函数的功能。以方便与自我复习和理解。