Prism Unity EventAggregator使用问题:跨模块刷新客户下拉框
Alright, let's tackle this problem step by step. Using Prism's EventAggregator is exactly the right approach here to communicate between your loosely coupled modules. Here's how to implement the auto-refresh of the customer dropdown in your Order module after creating a new customer in the Customer module:
1. 在Shared项目中定义全局事件类
First, we need a shared event that the Customer module can publish and the Order module can subscribe to. Create this in your Shared project so all modules can access it:
using Prism.Events; using YourAppName.Shared.Models; // 假设你有Customer实体类在这里 namespace YourAppName.Shared.Events { // 定义客户创建完成事件,携带新创建的客户对象(可选但推荐,避免全量刷新) public class CustomerCreatedEvent : PubSubEvent<Customer> { } }
2. 在Customer模块中发布事件
When a new customer is successfully created, we'll use the EventAggregator to publish this event. Update your Customer creation ViewModel:
using Prism.Events; using Prism.Mvvm; using Prism.Commands; using YourAppName.Shared.Events; using YourAppName.Shared.Models; using YourAppName.Shared.Services; // 假设你有保存客户的服务 namespace YourAppName.Modules.Customer.ViewModels { public class CreateCustomerViewModel : BindableBase { private readonly IEventAggregator _eventAggregator; private readonly ICustomerService _customerService; private Customer _newCustomer; public Customer NewCustomer { get => _newCustomer; set => SetProperty(ref _newCustomer, value); } public DelegateCommand SaveCustomerCommand { get; } public CreateCustomerViewModel(IEventAggregator eventAggregator, ICustomerService customerService) { _eventAggregator = eventAggregator; _customerService = customerService; NewCustomer = new Customer(); SaveCustomerCommand = new DelegateCommand(ExecuteSaveCustomer); } private void ExecuteSaveCustomer() { // 1. 先保存新客户到数据源(数据库/API等) _customerService.SaveCustomer(NewCustomer); // 2. 发布客户创建完成事件,通知所有订阅者 _eventAggregator.GetEvent<CustomerCreatedEvent>().Publish(NewCustomer); // 3. 关闭客户创建窗口(根据你的实现,比如用Prism的DialogService) CloseCreateCustomerWindow(); } private void CloseCreateCustomerWindow() { // 这里添加关闭窗口的逻辑,例如: // _dialogService.CloseDialog(this, true); } } }
3. 在Order模块中订阅事件并刷新下拉框
Now, in your Order module's ViewModel, subscribe to the CustomerCreatedEvent and update the customer dropdown when the event is received:
using Prism.Events; using Prism.Mvvm; using Prism.Commands; using Prism.Regions; using System.Collections.ObjectModel; using YourAppName.Shared.Events; using YourAppName.Shared.Models; using YourAppName.Shared.Services; namespace YourAppName.Modules.Order.ViewModels { public class OrderFormViewModel : BindableBase, IDestructible { private readonly IEventAggregator _eventAggregator; private readonly ICustomerService _customerService; private ObservableCollection<Customer> _customers; private Customer _selectedCustomer; private SubscriptionToken _customerCreatedToken; // 用于取消订阅 public ObservableCollection<Customer> Customers { get => _customers; set => SetProperty(ref _customers, value); } public Customer SelectedCustomer { get => _selectedCustomer; set => SetProperty(ref _selectedCustomer, value); } public DelegateCommand OpenCreateCustomerCommand { get; } public OrderFormViewModel(IEventAggregator eventAggregator, ICustomerService customerService) { _eventAggregator = eventAggregator; _customerService = customerService; OpenCreateCustomerCommand = new DelegateCommand(ExecuteOpenCreateCustomer); // 初始化加载客户列表 LoadCustomerList(); // 订阅客户创建事件 SubscribeToCustomerCreatedEvent(); } private void LoadCustomerList() { // 从共享服务获取所有客户 var customerList = _customerService.GetAllCustomers(); Customers = new ObservableCollection<Customer>(customerList); } private void ExecuteOpenCreateCustomer() { // 打开客户创建窗口的逻辑,例如用DialogService导航: // _dialogService.ShowDialog("CreateCustomerView"); } private void SubscribeToCustomerCreatedEvent() { // 订阅事件,指定在UI线程执行回调(因为要更新UI控件) _customerCreatedToken = _eventAggregator.GetEvent<CustomerCreatedEvent>() .Subscribe(OnCustomerCreated, ThreadOption.UIThread); } private void OnCustomerCreated(Customer newCustomer) { // 两种刷新方式选其一: // 方式1:高效直接添加新客户到集合(推荐,如果事件传递了新客户) Customers.Add(newCustomer); // 方式2:全量刷新列表(适合需要确保数据完全同步的场景) // LoadCustomerList(); } public void Destroy() { // 取消订阅,避免内存泄漏(Prism会在视图销毁时自动调用此方法) if (_customerCreatedToken != null) { _eventAggregator.GetEvent<CustomerCreatedEvent>().Unsubscribe(_customerCreatedToken); } } } }
关键注意事项
- 确保EventAggregator是单例:Prism Unity默认会将
IEventAggregator注册为单例,所以所有模块注入的是同一个实例,这是发布订阅生效的前提。 - UI线程更新:订阅时指定
ThreadOption.UIThread,因为UI控件只能在UI线程更新,Prism会自动帮你切换线程。 - 取消订阅:实现
IDestructible接口并在Destroy方法中取消订阅,防止内存泄漏。如果你的视图是通过Prism Region管理的,Prism会自动调用这个方法。 - 共享服务:使用
ICustomerService这样的共享服务来获取和保存客户数据,保证各个模块的数据一致性。
内容的提问来源于stack exchange,提问作者Matteo Beretta

