原文链接
https://learn.microsoft.com/zh-cn/archive/msdn-magazine/2014/june/mvvm-the-mvvm-light-messenger-in-depth
图1:发送和接收消息
public class Registration
{
public void SendUpdate()
{
var info = new RegistrationInfo { // ...一些属性 };
Messenger.Default.Send(info);
}
}
public class RegisteredUser
{
public RegisteredUser()
{
Messenger.Default.Register<RegistrationInfo>( this, HandleRegistrationInfo);
}
private void HandleRegistrationInfo(RegistrationInfo info)
{
// 更新已注册的用户信息
}
}
public class RegistrationInfo
{
// ...一些属性
}
图 2:使用命名方法或 Lambda 进行注册
public UserControl()
{
InitializeComponent();
// 使用命名方法进行注册 ----
Loaded += Figure2ControlLoaded;
Messenger.Default.Register<AnyMessage>( this, HandleAnyMessage);
// 使用匿名 Lambda 进行注册 ----
Loaded += (s, e) => {
// 执行某操作
};
Messenger.Default.Register<AnyMessage>( this, message => {
// 执行某操作
});
}
private void HandleAnyMessage(AnyMessage message)
{
// 执行某操作
}
private void Figure2ControlLoaded (object sender, RoutedEventArgs e)
{
// 执行某操作
}
跨线程访问
public void RunOnBackgroundThread()
{
// 执行某后台操作
DispatcherHelper.CheckBeginInvokeOnUI( () => {
Messenger.Default.Send(new ConfirmationMessage());
});
}
图 3:实例之间的强引用
public class Setup
{
private First _first = new First();
private Second _second = new Second();
public void InitializeObjects()
{
_first.AddRelationTo(_second);
}
public void Cleanup()
{
_second = null; // 即使 _second 实例设置为空,它也仍会保留在内存中,
//因为引用计数不为零,_first 仍引用它
}
}
public class First
{
private object _another;
public void AddRelationTo(object another)
{
_another = another;
}
}
public class Second { }
图 4:使用 WeakReference 实例
public class SuperSimpleMessenger
{
private readonly List<WeakReference> _receivers = new List<WeakReference>();
public void Register(IReceiver receiver)
{
_receivers.Add(new WeakReference(receiver));
}
public void Send(object message)
{
// 锁定接收端以免发生多线程问题。
lock (_receivers)
{
var toRemove = new List<WeakReference>();
foreach (var reference in _receivers.ToList())
{
if (reference.IsAlive)
{
((IReceiver)reference.Target).Receive(message);
}
else
{
toRemove.Add(reference);
}
}
// 删除无效引用。
// 在其他循环中执行此操作,以免在修改当前循环访问的集合时发生异常。
foreach (var dead in toRemove)
{
_receivers.Remove(dead);
}
}
}
}
图 6:使用默认的 Messenger 并检查发送端
public class FirstViewModel
{
public FirstViewModel()
{
Messenger.Default.Register<NotificationMessage>( this, message => {
if (message.Sender is MainViewModel)
{
// 此消息是要发送给我。
}
});
}
}
public class SecondViewModel
{
public SecondViewModel()
{
Messenger.Default.Register<NotificationMessage>( this, message => {
if (message.Sender is SettingsViewModel)
{
// 此消息是要发送给我
}
});
}
}
图 7:使用专用 Messenger
public class MainViewModel
{
private Messenger _privateMessenger;
public MainViewModel()
{
_privateMessenger = new Messenger();
SimpleIoc.Default.Register(() => _privateMessenger, "PrivateMessenger");
}
public void Update()
{
_privateMessenger.Send(new NotificationMessage("DoSomething"));
}
}
public class FirstViewModel
{
public FirstViewModel()
{
var messenger = SimpleIoc.Default.GetInstance<Messenger>("PrivateMessenger"); messenger.Register<NotificationMessage>( this, message => {
// 此消息是要发送给我。
});
}
}
图 8:使用令牌的不同信道
public class MainViewModel
{
public static readonly Guid Token = Guid.NewGuid();
public void Update()
{
Messenger.Default.Send(new NotificationMessage("DoSomething"), Token);
}
}
public class FirstViewModel
{
public FirstViewModel()
{
Messenger.Default.Register<NotificationMessage>( this, MainViewModel.Token, message => {
// 此消息是要发送给我。
});
}
}
图 9:使用消息类型来定义上下文
public class Sender
{
public void SendBoolean()
{
Messenger.Default.Send(true);
}
public void SendNotification()
{
Messenger.Default.Send( new NotificationMessage<bool>(true, Notifications.PlayPause));
}
}
public class Receiver
{
public Receiver()
{
Messenger.Default.Register<bool>( this, b => {
// 不确定如何处理此布尔。
});
Messenger.Default.Register<NotificationMessage<bool>>( this, message => {
if (message.Notification == Notifications.PlayPause)
{
// 对消息执行某操作。
Content. Debug.WriteLine(message.Notification + ":"+ message.Content);
}
});
}
}
图 10:发送 PropertyChangedMessage
public class BankViewModel :ViewModelBase
{
public const string BalancePropertyName = "Balance";
private double _balance;
public double Balance
{
get {
return _balance;
}
set {
if (Math.Abs(_balance - value) < 0.001)
{
return;
}
var oldValue = _balance;
_balance = value;
RaisePropertyChanged(BalancePropertyName, oldValue, value, true);
}
}
}
public class Receiver
{
public Receiver()
{
Messenger.Default.Register<PropertyChangedMessage<double>>( this, message => {
if (message.PropertyName == BankViewModel.BalancePropertyName)
{
Debug.WriteLine( message.OldValue + " --> " + message.NewValue);
}
});
}
}