WPF + Prism 技术指南与实战项目(一、自行搭建)

前言

在桌面客户端开发领域,WPF凭借强大的UI渲染能力、数据绑定机制和MVVM架构,是企业级桌面应用首选技术;而Prism作为WPF生态中成熟的MVVM框架,解决了模块化开发、导航、依赖注入、事件聚合等核心痛点,让大型项目代码高度解耦、可复用、易维护。Prism提供的 PrismApplication 类作为应用入口,统一管理依赖注入、模块加载和导航,使开发者能够专注于业务逻辑,实现高可维护性的桌面应用。


一、核心概念解析

为什么选择 WPF + Prism?
  • 原生MVVM支持: UI 与业务逻辑完全解耦,提升可维护性和可测试性。
  • 模块化架构: 功能模块独立开发,可按需加载或热插拔,降低大型项目的复杂度(需按规范配置模块)。
  • 内置依赖注入: 统一管理对象生命周期,减少耦合,便于扩展与重构。
  • 区域导航: 单窗口内多页面无缝切换,提升用户体验。
  • 事件聚合器: 跨模块、跨 ViewModel 解耦通信,简化全局消息传递。
  • 企业级稳定可靠: 由微软 Patterns & Practices 团队起源,社区维护,兼容 .NET Framework 4.6.1+ 及 .NET 6+,适合生产项目。
核心基础概念
  • MVVM:Model(数据)+ View(界面)+ ViewModel(逻辑),实现界面与业务解耦。
  • PrismApplication:Prism 应用入口,替代 App.xaml,支持 DI、模块加载和导航。
  • Region(区域):UI 容器,可动态加载和切换 View。
  • Module(模块):独立功能单元,支持按需加载和解耦开发。
  • Dependency Injection(DI):统一管理对象和依赖,默认 DryIoc,可选 Unity。
  • EventAggregator:跨模块、跨 ViewModel 的解耦消息传递。
相关资料

二、开发环境搭建

1. 环境要求
  • Visual Studio 2026(推荐)

  • .NET 8

  • Prism 9.0.537(最新版本,我习惯低一个版本8.1.97)

    00026.WPF + Prism 技术指南与实战项目(一、自行搭建)/
    ├── 01_自行搭建/


三、自行搭建

复制代码
01_自行搭建/        # 主解决方案文件夹(项目根目录)
├── Modules/        # 【模块目录】存放所有独立业务模块,实现解耦与按需加载
│   ├── ModuleA/    # 业务模块A(示例:用户管理模块)
│   │   ├── ViewModels/  # 模块A的ViewModel层(业务逻辑、状态管理)
│   │   │   └── UserControlAViewModel.cs
│   │   ├── Views/       # 模块A的View层(UI页面、用户控件)
│   │   │   └── UserControlA.xaml
│   │   └── ModuleA.cs   # 【模块入口】实现IModule接口,负责注册视图、初始化模块
│   └── ModuleB/    # 业务模块B(示例:订单管理模块/设置模块)
│       ├── ViewModels/  # 模块B的ViewModel层
│       │   └── UserControlBViewModel.cs
│       ├── Views/       # 模块B的View层
│       │   └── UserControlB.xaml
│       └── ModuleB.cs   # 模块B入口文件
├── Services/       # 【全局服务层】公共业务服务、工具类、接口定义
│   ├── IServices/ # 服务接口层(面向接口编程,便于解耦、测试、替换实现)
│   │   └── IDataService.cs
│   └── DataService.cs   # 服务具体实现(如数据请求、本地操作、公共方法)
├── App.xaml             # WPF应用声明文件,配置Prism框架启动
├── App.xaml.cs          # 【Prism入口】重写初始化方法,注册模块、服务、导航
├── MainWindow.xaml      # 主窗体View(定义Region区域、布局菜单)
├── MainWindow.xaml.cs   # 主窗体后台代码(Prism自动绑定,通常无业务代码)
└── MainWindowViewModel.cs # 主窗体ViewModel(菜单导航、全局状态控制)
结果:
1. 创建 WPF 项目
  1. 1.添加 01_自行搭建项目

  2. 2.安装 Prism 包

    • 采用管理NuGet包

    • 采用程序包管理器控制台安装

      Install-Package Prism.DryIoc -Version 9.0.537

视频转gif https://tool.bugcome.com/media-tools/video-convert/mp4-to-gif

2.配置 PrismApplication(App.xaml.cs)
复制代码
using _01_自行搭建.Modules.ModuleA;
using _01_自行搭建.Modules.ModuleB;
using _01_自行搭建.Services;
using _01_自行搭建.Services.IServices;
using System.Windows;

// Prism 核心命名空间(依赖注入、模块、应用程序基类)

namespace _01_自行搭建
{
    /// <summary>
    /// 应用程序入口类
    /// 继承 PrismApplication 实现 Prism 框架的初始化
    /// </summary>
    public partial class App : PrismApplication
    {
        /// <summary>
        /// 创建主窗口(Shell)
        /// Prism 应用程序必须指定一个主窗口作为启动界面
        /// </summary>
        protected override Window CreateShell()
        {
            return Container.Resolve<MainWindow>();
        }

        /// <summary>
        /// 注册全局服务、接口、ViewModel等
        /// 依赖注入容器注册中心
        /// </summary>
        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            // 注册全局服务:单例模式,接口与实现对应
            containerRegistry.RegisterSingleton<IDataService, DataService>();
        }

        /// <summary>
        /// 配置模块化
        /// 在这里注册所有需要加载的业务模块
        /// </summary>
        protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
        {
            // 注册模块A
            moduleCatalog.AddModule<ModuleA>();
            // 注册模块B
            moduleCatalog.AddModule<ModuleB>();
        }
    }
}

<!-- Prism 应用入口声明 -->
<!-- 继承自 PrismApplication,替代原生 WPF 的 Application,实现框架初始化 -->
<prism:PrismApplication 
    x:Class="_01_自行搭建.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:_01_自行搭建"
    xmlns:prism="http://prismlibrary.com/">

    <!-- 应用全局资源(样式、模板、转换器等存放位置) -->
    <Application.Resources>

    </Application.Resources>
</prism:PrismApplication>

视频转gif https://tool.bugcome.com/media-tools/video-convert/mp4-to-gif

参考代码:
  1. https://github.com/PrismLibrary/Prism/blob/master/src/Wpf/Prism.DryIoc.Wpf/PrismApplication.cs
  2. https://github.com/PrismLibrary/Prism/blob/master/src/Wpf/Prism.Wpf/PrismApplicationBase.cs
3.创建主窗口
复制代码
<!--  WindowStartupLocation="CenterScreen"  这句就是窗体居中 -->
    <Window x:Class="_01_自行搭建.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:local="clr-namespace:_01_自行搭建"
        mc:Ignorable="d"
        xmlns:prism="http://prismlibrary.com/"
        Title="MainWindow" Height="350" Width="525"  
        WindowStartupLocation="CenterScreen" 
        >
    
    <DockPanel>
        <StackPanel Orientation="Horizontal" DockPanel.Dock="Top">
            <Button Content="加载模块A" Command="{Binding LoadModuleACommand}" Margin="5"/>
            <Button Content="加载模块B" Command="{Binding LoadModuleBCommand}" Margin="5"/>
        </StackPanel>

        <ContentControl prism:RegionManager.RegionName="MainRegion"/>
    </DockPanel>
</Window>

// 命名空间:01_自行搭建(用于区分项目模块,方便管理)
namespace _01_自行搭建
{
    /// <summary>
    /// 主窗口的ViewModel
    /// 作用:处理主窗口的业务逻辑、命令、导航
    /// 继承 BindableBase:Prism 提供的基类,自动实现属性通知(INotifyPropertyChanged)
    /// </summary>
    public class MainWindowViewModel : BindableBase
    {
        // 区域管理器(Prism 核心服务)
        // 作用:用于在指定区域(Region)中导航、切换显示不同的用户控件/页面
        private readonly IRegionManager _regionManager;

        // 命令:加载模块A(导航到 UserControlA)
        // DelegateCommand 是 Prism 的命令,绑定到界面按钮点击事件
        public DelegateCommand LoadModuleACommand { get; }

        // 命令:加载模块B(导航到 UserControlB)
        public DelegateCommand LoadModuleBCommand { get; }

        /// <summary>
        /// 构造函数
        /// 依赖注入:自动传入 IRegionManager(Prism 框架自动注入)
        /// </summary>
        /// <param name="regionManager">区域管理器</param>
        public MainWindowViewModel(IRegionManager regionManager)
        {
            // 把注入的区域管理器赋值给局部变量
            _regionManager = regionManager;

            // 初始化命令:点击按钮 → 在 MainRegion 区域显示 UserControlA
            LoadModuleACommand = new DelegateCommand(() =>
                _regionManager.RequestNavigate("MainRegion", "UserControlA"));

            // 初始化命令:点击按钮 → 在 MainRegion 区域显示 UserControlB
            LoadModuleBCommand = new DelegateCommand(() =>
                _regionManager.RequestNavigate("MainRegion", "UserControlB"));
        }
    }
}
4. 创建模块(ModuleA 示例)
ModuleA.cs
复制代码
// 引入模块A的视图控件
using _01_自行搭建.Modules.ModuleA.Views;

// 模块A所在命名空间
namespace _01_自行搭建.Modules.ModuleA
{
    // 模块A类,实现Prism的IModule接口,代表这是一个可被自动加载的模块
    public class ModuleA : IModule
    {
        // 区域管理器(用于页面/控件导航)
        private readonly IRegionManager _regionManager;

        // 构造函数:依赖注入获取区域管理器
        public ModuleA(IRegionManager regionManager)
        {
            _regionManager = regionManager;
        }

        // 模块初始化方法:模块被加载时执行,可写初始化逻辑
        public void OnInitialized(IContainerProvider containerProvider)
        {
        }

        // 注册类型:把视图注册到Prism导航系统,才能用RequestNavigate跳转
        public void RegisterTypes(IContainerRegistry containerRegistry)
        {
            // 注册UserControlA,允许通过导航名称"UserControlA"调用
            containerRegistry.RegisterForNavigation<UserControlA>();
        }
    }
}
UserControlA.xaml
复制代码
<UserControl x:Class="_01_自行搭建.Modules.ModuleA.Views.UserControlA"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d" 
             d:DesignHeight="200" d:DesignWidth="400">
	<!-- 布局容器:浅蓝色背景 -->
    <Grid Background="LightBlue">
	<!-- 居中显示文字:模块A内容 -->
        <TextBlock Text="这是模块A的内容" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="20"/>
    </Grid>
</UserControl>
UserControlAViewModel.cs
复制代码
namespace _01_自行搭建.Modules.ModuleA.ViewModels
{
    /// <summary>
    /// UserControlA 的视图模型(MVVM 中的 VM)
    /// 作用:给界面提供数据、命令、业务逻辑
    /// </summary>

    // BindableBase:Prism 基类,实现了 INotifyPropertyChanged
    // 作用:当属性值变化时,自动通知界面刷新(实现绑定更新)
    public class UserControlAViewModel : BindableBase
    {
        // 将来在这里写:
        // 1. 绑定到界面的属性(如文本、列表、状态)
        // 2. 按钮命令、业务方法
        // 3. 界面交互逻辑
    }
}
5. 创建服务(可选)
IDataService.cs
复制代码
// 引入系统基础库
// 接口所在命名空间(服务层接口)
namespace _01_自行搭建.Services.IServices
{
    // 数据服务接口:定义方法规范,不写具体实现
    public interface IDataService
    {
        // 接口方法:获取数据,返回字符串
        string GetData();
    }
}
DataService.cs
复制代码
// 引入服务接口(必须引用,才能实现接口)
using _01_自行搭建.Services.IServices;

// 服务实现类所在命名空间
namespace _01_自行搭建.Services
{
    /// <summary>
    /// 数据服务实现类
    /// 实现 IDataService 接口,提供具体方法逻辑
    /// </summary>
    public class DataService : IDataService
    {
        /// <summary>
        /// 实现接口方法:返回测试数据
        /// </summary>
        /// <returns>测试字符串</returns>
        public string GetData() => "Prism 服务数据示例";
    }
}

四、Prism 开发最佳实践

  1. 严格遵循 MVVM
  • View 只做界面布局与绑定,严禁后台代码写业务逻辑
  • ViewModel 统一处理业务逻辑、数据状态与命令逻辑
  1. 区域命名规范
  • 统一遵循 XXXRegion 命名格式,项目全局统一规范
  1. 模块拆分原则
  • 按业务领域拆分模块,保证职责单一,拒绝臃肿大模块
  1. 依赖注入优先
  • 禁止手动 new 创建实例,全靠容器注入,方便解耦与单元测试
  1. 事件聚合慎用
  • 仅用于跨模块无依赖通信,同模块优先直接调用,避免消息混乱
  1. 导航参数传递
  • 统一使用 NavigationParameters 传参,摒弃静态变量传参
  1. 生命周期管理
  • ViewModel 实现 INavigationAware,合理做页面初始化与资源释放

五、总结

WPF + Prism 是企业级桌面开发成熟技术组合,核心优势:

  • MVVM 架构:实现界面与业务逻辑完全分离
  • 模块化开发:业务划分清晰,易维护、易扩展、支持按需加载
  • 依赖注入:精简代码耦合,统一管控对象生命周期
  • 区域导航:轻松实现复杂布局与内部页面无缝跳转

熟练运用以上开发规范,能有效解决传统桌面项目耦合严重、维护困难、扩展性差等问题。学习 Prism 重在理解解耦设计思想,而非死记接口用法,结合项目实战即可快速开发稳定商用级桌面客户端。


👋 关注我!持续分享 C# / WPF 实战技巧、代码示例 & 技术干货 & 开发工具网站

  • 获取示例代码,轻松上手!
  • 私信输入数字: jpmz
  • 获取代码下载链接
相关推荐
她说彩礼65万1 天前
WPF Border
wpf
He BianGu1 天前
【笔记】在WPF中在IValueConverter 时“无法返回有效值该怎么做”
笔记·wpf
海兰1 天前
使用 OpenTelemetry 与 Elastic APM 追踪 MCP 服务器工具调用
运维·服务器·elasticsearch·wpf
咩图2 天前
WPF-VisualStudio-C#-Fluent.Ribbon8.0.0学习
c#·wpf·visual studio
拼尽全力前进2 天前
JDDL 核心实现原理与架构解析
架构·wpf
加号32 天前
【C#】WPF基于Halcon 的HWindowControlWPF 控件实现图像缩放、移动
开发语言·c#·wpf
码农的神经元2 天前
考虑通信时延的直流微电网分布式电-氢混合储能协同控制仿真复现与改进
分布式·wpf
Kimhill张2 天前
.net core8 WPF 依赖注入(DI)
wpf·.netcore
△曉風殘月〆3 天前
如何在WPF中使用 Fluent 主题
wpf