惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
博客园 - 三生石上(FineUI控件)
S
Securelist
U
Unit 42
The Cloudflare Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Simon Willison's Weblog
Simon Willison's Weblog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
B
Blog
T
Tenable Blog
The Hacker News
The Hacker News
The Register - Security
The Register - Security
IT之家
IT之家
博客园 - 【当耐特】
Spread Privacy
Spread Privacy
P
Privacy & Cybersecurity Law Blog
博客园_首页
T
Tailwind CSS Blog
人人都是产品经理
人人都是产品经理
C
Cybersecurity and Infrastructure Security Agency CISA
Know Your Adversary
Know Your Adversary
NISL@THU
NISL@THU
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
阮一峰的网络日志
阮一峰的网络日志
T
Tor Project blog
C
CERT Recently Published Vulnerability Notes
Apple Machine Learning Research
Apple Machine Learning Research
Stack Overflow Blog
Stack Overflow Blog
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
V
Vulnerabilities – Threatpost
A
Arctic Wolf
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
V
V2EX
aimingoo的专栏
aimingoo的专栏
大猫的无限游戏
大猫的无限游戏
Scott Helme
Scott Helme
L
LINUX DO - 热门话题
Cyberwarzone
Cyberwarzone
V
Visual Studio Blog
月光博客
月光博客
爱范儿
爱范儿
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
美团技术团队
G
GRAHAM CLULEY
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
H
Heimdal Security Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO

博客园 - HackerVirus

在window系统下搭建C/C++开发环境 C#中DataGridView处理大数据量的技巧分享 CSharp-MVVM框架 多线程&线程池 Toggling Focus Assist mode in Win 10 Programmatically Windsurf:超越 Cursor 的下一代 AI 编辑器 编程辅助新选择:Devin与Cursor的性能对比评测 支持多语言、多商店的商城,.Net7 + EF7领域驱动设计架构 Mysql高可用架构方案 软件架构中的那些惯用手段 .Net轻量级的CMS开源项目 前后端分离的权限管理框架,前端采用 Vue 3 框架,后端采用 .NET 8、ORM 采用 EF 8 linux文件属性 Roslyn的源生成器 IHostedService 和 BackgroundService 区别 Uno Platform是一个基于C#开源、功能强大、灵活的跨平台开发框架,用于快速构建单一代码库原生移动、Web、桌面和嵌入式应用程序 使用HslCommunication类库读取Siemens PLC DATA 功能齐全的 WPF 自定义控件 Sprint Planning
Prism的事件聚合器
HackerVirus · 2026-04-16 · via 博客园 - HackerVirus

.NET Core 3 WPF MVVM框架 Prism系列文章索引

https://www.cnblogs.com/ryzen

关于Prism的依赖注入容器如何使用应该都已明了,今天我们来讲一下如何使用Prism的事件聚合器。
我们分三步走:

  1. 第一,在MVVM项目开发中如何使用事件?
    首先我们需要先知道事件是什么,事件其实就是委托的一种安全封装,从层级上来说,委托是引用类型,事件是一种成员。详解可见https://www.cnblogs.com/wangjiming/p/8300103.html 个人觉得相对友好的文。
    在WPF开发中,无论何时都离不开事件。如按下按钮后文本框更新显示welcome,最简单的就是直接在welcome事件里修改文本框文本。如果按钮与命令Binding在一起,那么事件中也会挂接命令执行方法,也就是说按下按钮事件依旧执行,只不过事件内部为命令方法。假设现在需要进行多页面开发,按下第一页按钮,第二页数据表格需同步更新,那么这里肯定就离不开事件。
    在正式讲解事件聚合器之前,由于需要用实际例子演示如何通过事件在不同控件或者页面之间进行通信。关于WPF开发中的不同界面是如何实现的:https://www.cnblogs.com/weskynet/p/15967764.html
    //这里模拟一个空的Login界面。2个文本框一个班接收密码,密码成功核对后提示bingo。登录成功后表格主窗口显示记录所有尝试登录的用户名称和密码及登录状态。

夸克录屏_2026-01-14_12-02-23

首先,先定义好登录的一些状态信息//Model/LoginAttempt.cs
image
然后是定义登录页面//LoginPage.axmal
image
定义对应的axaml.cs//LoginPage.axmal.cs
image
至此,第一个界面设计完成,这个界面是需要显示在主窗口之前的,也就是在Login界面登录成功后才会进入主界面。接下来我们来写主窗口界面。
界面如图:

image

点击查看MainWindow.axmal代码

//MainWindow.axmal
<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="using:PubEvent.ViewModels"
        xmlns:models="using:PubEvent.Models"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
        x:Class="PubEvent.Views.MainWindow"
        x:DataType="vm:MainWindowViewModel"
        Icon="/Assets/avalonia-logo.ico"
        Title="PubEvent">

    <Design.DataContext>
        <vm:MainWindowViewModel/>
    </Design.DataContext>

    <Grid RowDefinitions="Auto,Auto,*" Margin="10">
        <TextBlock Text="登录记录" 
                   FontSize="20" 
                   FontWeight="Bold"
                   HorizontalAlignment="Center" 
                   Margin="0,10"/>
        
        

对应的MainWindow.axmal.cs

image

好的,这里View已经完成,接下来实现对应的事件以及ViewModel层
先定义好事件类,创建一个尝试登录的事件LoginAttempted。代码如图:

image

随后需要在LoginPageViewMode中定义好LoginPage中Button的命令(命令执行需触发事件),在MainWindowViewMode中定义好DataGrid数据来源,订阅以及执行事件方法(事件方法内更新DataGrid)。

点击查看LoginPageViewMode.cs代码

//LoginPageViewMode.cs(需要定义页面切换逻辑,带触发事件的命令,供View绑定的空构造,View绑定的两个Text。)
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MsBox.Avalonia;
using MsBox.Avalonia.Enums;
using PubEvent.Events;
using PubEvent.Models;

namespace PubEvent.ViewModels;

public partial class LoginPageViewModel : ObservableObject
{
    [ObservableProperty]
    private string? _username;
    [ObservableProperty]
    private string? _password;

    [RelayCommand]
    private async Task Login()
    {
        if (string.IsNullOrEmpty(Username) || string.IsNullOrEmpty(Password))
        {
            

点击查看MainWindowViewModel代码

//MainWindowViewModel.cs(需要定义好DataGrid数据列表,定义事件方法并订阅执行,加载LoginPage的数据缓存<必须有缓存,不然在触发事件时MainWindowViewModel还没生成,无法执行DataGrid更新>)
using System;
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using PubEvent.Events;
using PubEvent.Models;

namespace PubEvent.ViewModels;

public partial class MainWindowViewModel : ObservableObject
{
    
    

以上整体开发就已经大致完成,接下来在App初始化上需要注册对应的窗口以便切换,并定义好切换执行方法以及缓存的方法。点击查看App.axmal.cs代码

//App.axmal.cs(需要定义好初始化窗口执行LoginPage。窗口切换方法SwitchToMainWindow,缓存方法AddLoginAttempt)
using System.Collections.Generic;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Prism.DryIoc;
using Prism.Ioc;
using PubEvent.Models;
using PubEvent.ViewModels;
using PubEvent.Views;

namespace PubEvent;

public partial class App : PrismApplication
{
    

附带App.axmal代码(这里使用了容器注册做界面切换,所以需要使用PrismApplication)点击查看App.axmal代码

<prism:PrismApplication xmlns="https://github.com/avaloniaui"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:prism="http://prismlibrary.com/"
             x:Class="PubEvent.App"
             RequestedThemeVariant="Default">
             

2. **第二,如何在不同页面间使用事件聚合器?** 从前文我们已经可以看出在进行多界面开发中,总会有页面间的信息交互需要通过事件进行,例如A页面的某个Button按下后需要保存页面信息显示在B页面。如果采用传统事件的订阅发布,就依旧会有强耦合性,无论是事件订阅和发布都是如此。从软件架构上来说,这样不适合进行模块测试。所以引入了事件聚合器,接下来我们看看事件聚合器如何实现以上例子。 这里因为只是为了解耦,其实本质就是依赖于抽象不依赖于具体实现,所以这里我们只用修改前文部分的三处代码即可。分别是定义好的事件类LoginAttemptEvent.cs;登录页的LoginPageViewModel以及主窗口的MainWindowViewModel。 * **1、//LoginAttemptEvent.cs(事件类继承自PubEvent,内部实现了IEventAggregator接口)**

image

点击查看代码

using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MsBox.Avalonia;
using MsBox.Avalonia.Enums;
using Prism.Events;
using PubEvent.Events;
using PubEvent.Models;

namespace PubEvent.ViewModels;

public partial class LoginPageViewModel : ObservableObject
{
    [ObservableProperty]
    private string? _username;
    [ObservableProperty]
    private string? _password;
    
    private readonly IEventAggregator? _eventAggregator;

    public LoginPageViewModel(IEventAggregator eventAggregator)
    {
        _eventAggregator = eventAggregator;
    }
    
    

* **3、//MainWindowViewModel.cs(一样注入IEventAggregator,实现接口方法订阅)**点击查看代码

using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using Prism.Events;
using PubEvent.Events;
using PubEvent.Models;

namespace PubEvent.ViewModels;

public partial class MainWindowViewModel : ObservableObject
{
    
    

3、使用事件聚合器的优势在哪?为何要用?
从以上两个例子应该能很好的看出来了,使用事件聚合器能够少量的减少代码,将所有需要的事件服务都继承自PubEvent,不仅方便代码框架维护,同时它带来的解耦便利性也可以方便团队划分模块开发,还能够进行模块化的测试,对于大型应用来说这种架构是必须的。以上为我个人快速学习的简短理解,希望能够有所帮助。