在Prism中,有一个重要的功能,就是事件聚合器,也就是消息机制,是大家常用的功能。主要是为了实现不同模块之间的信息交互。在prism的官方demo中也给出了简单的使用例子。但是在实际使用过程中,模块多了,消息多了,会非常的难调试,因此我这里对消息机制做了一次封装,并且统一去管理定义各个模块用到的消息。代码比较简单,我这里只是对官方的例子做了一个改造,大家可以参考一下。红色为主要改动的部分,代码结构如下图:
主要代码如下:
SendMessageMsg.cs
namespace UsingEventAggregator.Core.Messages
{
public class SendMessageMsg
{
public string SendMessage { get; set; }
}
}
FrameMessenger.cs
using Prism.Events;
using Prism.Ioc;
using System;
namespace UsingEventAggregator.Core
{
public class FrameMessenger
{
private static readonly FrameMessenger _instance = new FrameMessenger();
private readonly IEventAggregator _eventAggregator;
public static FrameMessenger Instance
{
get { return _instance; }
}
private FrameMessenger()
{
_eventAggregator = (IEventAggregator)ContainerLocator.Container.Resolve(typeof(IEventAggregator));
}
///
/// 发布方法
///
/// 泛型
/// T类型消息
public void Publish<T>(T t)
{
_eventAggregator.GetEvent<PubSubEvent<T>>().Publish(t);
}
///
/// 订阅T类型消息
///
/// 泛型
/// 订阅方法,用于执行接受消息的动作
public void Subscribe<T>(Action<T> action)
{
_ = _eventAggregator.GetEvent<PubSubEvent<T>>().Subscribe(action);
}
///
/// 订阅T类型消息,且增加过滤条件
///
/// 泛型
/// 订阅方法,用于执行接受消息的动作
/// 过滤条件
public void Subscribe<T>(Action<T> action, Predicate<T> filter)
{
_ = _eventAggregator.GetEvent<PubSubEvent<T>>().Subscribe(action, filter);
}
///
/// 订阅T类型消息,且增加过滤条件,是否同步执行,保持强引用
///
/// 泛型
/// 订阅方法,用于执行接受消息的动作
/// 过滤条件
/// 是否同步
/// 是否保持强引用
public void Subscribe<T>(Action<T> action, Predicate<T> filter = null, bool sync = false, bool keepSubscriberReferenceAlive = false)
{
_ = _eventAggregator.GetEvent<PubSubEvent<T>>().Subscribe(action,
sync ? ThreadOption.PublisherThread : ThreadOption.BackgroundThread,
keepSubscriberReferenceAlive,
filter);
}
///
/// 取消订阅
///
/// 泛型
/// 订阅方法
public void Unsubscribe<T>(Action<T> action)
{
_eventAggregator.GetEvent<PubSubEvent<T>>().Unsubscribe(action);
}
}
}
MainWindowViewModel.cs
using Prism.Mvvm;
namespace UsingEventAggregator.ViewModels
{
public class MainWindowViewModel : BindableBase
{
private string _title = "Prism Unity Application";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
public MainWindowViewModel()
{
}
}
}
MainWindow.xaml
<Window x:Class="UsingEventAggregator.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/"
prism:ViewModelLocator.AutoWireViewModel="True"
Title="{Binding Title}" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
Grid.ColumnDefinitions>
<ContentControl prism:RegionManager.RegionName="LeftRegion" />
<ContentControl Grid.Column="1" prism:RegionManager.RegionName="RightRegion" />
Grid>
Window>
MessageViewModel.cs
using Prism.Commands;
using Prism.Mvvm;
using UsingEventAggregator.Core;
using UsingEventAggregator.Core.Messages;
namespace ModuleA.ViewModels
{
public class MessageViewModel : BindableBase
{
private string _message = "Message to Send";
public string Message
{
get { return _message; }
set { SetProperty(ref _message, value); }
}
public DelegateCommand SendMessageCommand { get; private set; }
public MessageViewModel()
{
SendMessageCommand = new DelegateCommand(SendMessage);
}
private void SendMessage()
{
FrameMessenger.Instance.Publish<SendMessageMsg>(new SendMessageMsg {SendMessage= Message });
}
}
}
MessageView.xaml
<UserControl x:Class="ModuleA.Views.MessageView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True" Padding="25">
<StackPanel>
<TextBox Text="{Binding Message}" Margin="5"/>
<Button Command="{Binding SendMessageCommand}" Content="Send Message" Margin="5"/>
StackPanel>
UserControl>
ModuleAModule.cs
using ModuleA.Views;
using Prism.Ioc;
using Prism.Modularity;
using Prism.Regions;
namespace ModuleA
{
public class ModuleAModule : IModule
{
public void OnInitialized(IContainerProvider containerProvider)
{
var regionManager = containerProvider.Resolve<IRegionManager>();
regionManager.RegisterViewWithRegion("LeftRegion", typeof(MessageView));
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
}
}
}
MessageListViewModel.cs
using Prism.Events;
using Prism.Mvvm;
using System.Collections.ObjectModel;
using UsingEventAggregator.Core;
using UsingEventAggregator.Core.Messages;
namespace ModuleB.ViewModels
{
public class MessageListViewModel : BindableBase
{
private ObservableCollection<string> _messages;
public ObservableCollection<string> Messages
{
get { return _messages; }
set { SetProperty(ref _messages, value); }
}
public MessageListViewModel()
{
Messages = new ObservableCollection<string>();
FrameMessenger.Instance.Subscribe<SendMessageMsg>(MessageReceived);
}
private void MessageReceived(SendMessageMsg message)
{
Messages.Add(message.SendMessage);
}
}
}
MessageList.xaml
<UserControl x:Class="ModuleB.Views.MessageList"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True" Padding="25">
<Grid>
<ListBox ItemsSource="{Binding Messages}" />
Grid>
UserControl>
ModuleBModule.cs
using ModuleB.Views;
using Prism.Ioc;
using Prism.Modularity;
using Prism.Regions;
namespace ModuleB
{
public class ModuleBModule : IModule
{
public void OnInitialized(IContainerProvider containerProvider)
{
var regionManager = containerProvider.Resolve<IRegionManager>();
regionManager.RegisterViewWithRegion("RightRegion", typeof(MessageList));
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
}
}
}