WPF开发之Prism详解【内附源码】

简介: WPF开发之Prism详解【内附源码】

在实际应用开发中,随着项目业务逐渐复杂,耦合度会越来越高,维护成本也会直线上升,所以解耦也变得越来越重要。Prism框架为WPF开发中解耦提供了非常便捷的应用。今天主要以一个简单的小例子,简述WPF开发中Prism框架的简单应用,如有不足之处,还请指正。

什么是Prism

Prism是一个开源框架,用于在WPF、Xamarin Forms、Uno/Win UI等应用中创建松耦合、可维护、可测试的XAML应用程序。Prism提供了一组设计模式的实现,这些设计模式有助于编写结构良好且可维护的XAML应用程序,包括MVVM,dependency injection,commands,EventAggregator等。

Prism源码库

Prism遵守开源许可协议(MIT),目前最新版本8.1.97,可通过GitHub进行下载最新版本。https://github.com/PrismLibrary

Prism优点

Prism 设计围绕核心建筑设计原则,即关注点分离和松散耦合。这使得Prism可以提供许多好处

  • 重复使用:通过重复使用单元测试的组件,可以通过依赖性注入在运行时间轻松发现和集成,以及通过使用可在应用程序中重复使用的应用程序级功能封装模块,在应用级别实现重复使用。
  • 可扩展性:通过管理组件依赖性、使组件在运行时间更容易集成或替换为替代实现以及提供将应用程序分解为可独立更新和部署的模块的能力,帮助创建易于扩展的应用程序
  • 灵活性:Prism 有助于创建灵活的应用程序,使它们能够随着新功能的开发和集成而更容易更新
  • 团队发展:Prism 有助于最大限度地减少跨团队依赖性,并允许团队专注于不同的功能领域(如 UI 设计、业务逻辑实现和基础架构代码开发),或不同业务级别的功能领域(如简介、销售、库存或物流)。

 

模块化思想

通过对比发现,采用模块化思想进行设计,使得程序结构清晰,符合高内聚,低耦合的设计风格。

 

 

Prism安装

Prism可通过NuGet方案包管理器进行安装,主要安装三个Prism.Core,Prism.Unity,Prism.Wpf

 

创建模块和视图控件

创建WPF类库,并添加用户控件视图,并采用MVVM开发模式

 

数据绑定

在Prism框架中,提供了数据绑定基类Prism.Mvvm.BindableBase,可以方便的将普通属性,转换为依赖属性,简化开发中过程中的代码量。

namespace DemoPrism.Second.ViewModels
{
    internal class SecondViewModel : BindableBase
    {
        #region 属性及构造函数
        private int id;
        public int Id
        {
            get { return id; }
            set { SetProperty(ref id, value); }
        }
        /// <summary>
        /// 模块间交互
        /// </summary>
        private readonly IEventAggregator eventAggregator;
        public SecondViewModel(IEventAggregator eventAggregator)
        {
            this.eventAggregator = eventAggregator;
            this.eventAggregator.GetEvent<DemoOneEvent>().Subscribe(DemoOneRecived);
        }
        #endregion
        private void DemoOneRecived(int id)
        {
            this.Id = id;
        }
    }
}

创建Prism模块

添加Module类,并实现Prism.Modularity.IModule接口,实现接口的模块,视为可以被Prism发现并加载的模块。以DefectListModule模块为例:

namespace DemoPrism.First
{
    public class FirstModule : IModule
    {
        public void OnInitialized(IContainerProvider containerProvider)
        {
            IRegionManager regionManager = containerProvider.Resolve<IRegionManager>();
            regionManager.RegisterViewWithRegion("FirstRegion", typeof(Views.FirstView));
        }
        public void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterForNavigation<Views.FirstView, ViewModels.FirstViewModel>();
        }
    }
}

模块配置

Prism提供了多种模块加载方式,常用的有App.config配置文件方法。

  1. 在App.config节点,添加configSections配置,增加modules节点配置
  2. modules节点主要配置需要加载的Prism模块
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <!--prism配置-->
    <section name="modules" type="Prism.Modularity.ModulesConfigurationSection, Prism.Wpf"/>
  </configSections>
  <modules>
    <!--注册模块-->
    <module assemblyFile="Modules\DemoPrism.First.dll" moduleType="DemoPrism.First.FirstModule, DemoPrism.First" moduleName="First" startupLoaded="true" />
    <module assemblyFile="Modules\DemoPrism.Second.dll" moduleType="DemoPrism.Second.SecondModule, DemoPrism.Second" moduleName="Second" startupLoaded="true" />
  </modules>
</configuration>

模块加载

模块配置好后,需要在启动的时候,加载模块。修改WPF入口启动程序,App.xaml.cs文件,继承自Prism.Unity.PrismApplication基类,并重写相关初始化

 

namespace DemoPrism
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : PrismApplication
    {
        //使用容器创建主窗体
        protected override Window CreateShell() => Container.Resolve<MainWindow>();
        protected override void ConfigureViewModelLocator()
        {
            base.ConfigureViewModelLocator();
        }
        protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
        {
            //通过代码的方式添加模块
            //moduleCatalog.AddModule<NavigationModule.NavigationModule>();
            //将MedicineModule模块设置为按需加载
            base.ConfigureModuleCatalog(moduleCatalog);
        }
        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
        }
        protected override IModuleCatalog CreateModuleCatalog()
        {
            ConfigurationModuleCatalog configurationModuleCatalog = new ConfigurationModuleCatalog();
            configurationModuleCatalog.Load();
            //通过Xaml配置文件读取模块加载信息
            return configurationModuleCatalog;
            //return directoryModuleCatalog;
        }
        /// <summary>
        /// 注册适配器(区域容器:Region)
        /// </summary>
        /// <param name="regionAdapterMappings"></param>
        protected override void ConfigureRegionAdapterMappings(RegionAdapterMappings regionAdapterMappings)
        {
            base.ConfigureRegionAdapterMappings(regionAdapterMappings);
        }
    }
}

 

区域Region

在Prism框架中,模块可以注册到导航菜单Navigation,也可以注册到区域Region,根据实际业务需要进行选择。Region可以更加方便的进行模块化布局等。在普通容器控件中,增加prism:RegionManager.RegionName=”名称”

<Window x:Class="DemoPrism.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:prism="http://prismlibrary.com/"
        xmlns:local="clr-namespace:DemoPrism"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        prism:ViewModelLocator.AutoWireViewModel="True">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <ContentControl Grid.Column="0" prism:RegionManager.RegionName="FirstRegion"></ContentControl>
        <ContentControl Grid.Column="1" prism:RegionManager.RegionName="SecondRegion"></ContentControl>
    </Grid>
</Window>

模块交互

模块与模块之间相互独立,如果需要交互,可以通过事件聚合器IEventAggregator,采用事件的订阅和发布进行通信。

事件订阅步骤:

  1. 定义事件,定义一个类,继承自Prism.Events.PubSubEvent泛型类
  2. 事件发布,通过事件聚合器的Publish方法进行发布。
  3. 事件订阅,通过事件聚合器的Subscribe进行订阅。
namespace DemoPrism.Event
{
    /// <summary>
    /// 注册事件
    /// </summary>
    public class DemoOneEvent : PubSubEvent<int>
    {
    }
}

弹出模态窗口

在Prism框架下,弹出模态窗口,需要以下3个步骤:

  1. 在Prism框架中,页面UserControl实现弹窗功能,被弹出页面需要实现Prism.Services.Dialogs.IDialogAware接口。
  2. 注册窗口,将UserControl注册成窗口。
  3. 调用弹出服务,弹出窗口
相关文章
|
2月前
|
C# 开发者 Windows
WPF 应用程序开发:一分钟入门
本文介绍 Windows Presentation Foundation (WPF),这是一种用于构建高质量、可缩放的 Windows 桌面应用程序的框架,支持 XAML 语言,方便 UI 设计与逻辑分离。文章涵盖 WPF 基础概念、代码示例,并深入探讨常见问题及解决方案,包括数据绑定、控件样式与模板、布局管理等方面,帮助开发者高效掌握 WPF 开发技巧。
163 65
|
1月前
|
设计模式 前端开发 C#
使用 Prism 框架实现导航.NET 6.0 + WPF
使用 Prism 框架实现导航.NET 6.0 + WPF
84 10
|
3月前
|
开发框架 前端开发 JavaScript
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(12) -- 使用代码生成工具Database2Sharp生成WPF界面代码
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(12) -- 使用代码生成工具Database2Sharp生成WPF界面代码
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(12) -- 使用代码生成工具Database2Sharp生成WPF界面代码
|
3月前
|
开发框架 缓存 前端开发
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(11) -- 下拉列表的数据绑定以及自定义系统字典列表控件
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(11) -- 下拉列表的数据绑定以及自定义系统字典列表控件
|
3月前
|
开发框架 前端开发 JavaScript
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(10) -- 在DataGrid上直接编辑保存数据
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(10) -- 在DataGrid上直接编辑保存数据
|
3月前
|
开发框架 前端开发 JavaScript
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(5) -- 树列表TreeView的使用
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(5) -- 树列表TreeView的使用
|
3月前
|
测试技术 C# 开发者
“代码守护者:详解WPF开发中的单元测试策略与实践——从选择测试框架到编写模拟对象,全方位保障你的应用程序质量”
【8月更文挑战第31天】单元测试是确保软件质量的关键实践,尤其在复杂的WPF应用中更为重要。通过为每个小模块编写独立测试用例,可以验证代码的功能正确性并在早期发现错误。本文将介绍如何在WPF项目中引入单元测试,并通过具体示例演示其实施过程。首先选择合适的测试框架如NUnit或xUnit.net,并利用Moq模拟框架隔离外部依赖。接着,通过一个简单的WPF应用程序示例,展示如何模拟`IUserRepository`接口并验证`MainViewModel`加载用户数据的正确性。这有助于确保代码质量和未来的重构与扩展。
81 0
|
3月前
|
前端开发 C# 设计模式
“深度剖析WPF开发中的设计模式应用:以MVVM为核心,手把手教你重构代码结构,实现软件工程的最佳实践与高效协作”
【8月更文挑战第31天】设计模式是在软件工程中解决常见问题的成熟方案。在WPF开发中,合理应用如MVC、MVVM及工厂模式等能显著提升代码质量和可维护性。本文通过具体案例,详细解析了这些模式的实际应用,特别是MVVM模式如何通过分离UI逻辑与业务逻辑,实现视图与模型的松耦合,从而优化代码结构并提高开发效率。通过示例代码展示了从模型定义、视图模型管理到视图展示的全过程,帮助读者更好地理解并应用这些模式。
96 0
|
3月前
|
容器 C# Docker
WPF与容器技术的碰撞:手把手教你Docker化WPF应用,实现跨环境一致性的开发与部署
【8月更文挑战第31天】容器技术简化了软件开发、测试和部署流程,尤其对Windows Presentation Foundation(WPF)应用程序而言,利用Docker能显著提升其可移植性和可维护性。本文通过具体示例代码,详细介绍了如何将WPF应用Docker化的过程,包括创建Dockerfile及构建和运行Docker镜像的步骤。借助容器技术,WPF应用能在任何支持Docker的环境下一致运行,极大地提升了开发效率和部署灵活性。
119 0
|
3月前
|
区块链 C# 存储
链动未来:WPF与区块链的创新融合——从智能合约到去中心化应用,全方位解析开发安全可靠DApp的最佳路径
【8月更文挑战第31天】本文以问答形式详细介绍了区块链技术的特点及其在Windows Presentation Foundation(WPF)中的集成方法。通过示例代码展示了如何选择合适的区块链平台、创建智能合约,并在WPF应用中与其交互,实现安全可靠的消息存储和检索功能。希望这能为WPF开发者提供区块链技术应用的参考与灵感。
62 0