WPF 消息传递简明教程

WPF 消息传递简明教程

WPF 消息传递简明教程

独立观察员 2023 年 4 月 24 日

0、说明

参考:https://www.cnblogs.com/cdaniu/p/16852620.html 

使用包:CommunityToolkit.Mvvm(8.1.0)

 

1、订阅

让需要使用消息的 ViewModel 继承 ObservableRecipient,构造函数中设置 IsActive=true:

WPF 消息传递简明教程

 

重写 OnActivated () 和 OnDeactivated () 方法:

#region 消息处理

/// <summary>
/// 注册消息接收  
/// </summary>
protected override void OnActivated()
{
    WeakReferenceMessenger.Default.Register<MainWindowViewModel, MyMessage, string>(this,
        nameof(MyMessage), OnReceiveMessage);
}

/// <summary>
/// 收到消息时的处理方法
/// </summary>
/// <param name="recipient">接收者</param>
/// <param name="message">消息</param>
private void OnReceiveMessage(MainWindowViewModel recipient, MyMessage message)
{
    //处理逻辑;
}

/// <summary>
/// 注销消息接收
/// </summary>
protected override void OnDeactivated()
{
    base.OnDeactivated();
    WeakReferenceMessenger.Default.Unregister<MyMessage, string>(this, nameof(MyMessage));
}

#endregion

 

解释:

WPF 消息传递简明教程

 

2、发送消息

var message = new MyMessage()
{
    //属性赋值,
};
WeakReferenceMessenger.Default.Send(message, nameof(MyMessage));

 

3、注意事项

主要用法就是上面两点,还是挺简单的,但是网上的文章却看得人云里雾里的。这一节说一些注意事项。

 

3.1、消息类型不要混用

消息类应当是每个消息专用的,推荐使用 sealed 标记:

WPF 消息传递简明教程

 

3.2、订阅要在发送之前执行

这一条大家可能会觉得这有什么好提醒的,本来就要这样啊。但是,实际写的时候,还是容易发生执行到发送的逻辑时,订阅的那部分代码实际还没执行,通常就是那个 ViewModel 还没出生呢。不过这个也很好排查出来,一般出现发了消息,但是消息处理方法那里没反应,就是这个问题了。解决方法就是让订阅的对象先生成出来即可,只不过有的时候这样可能没什么道理,大家有更好的方法,欢迎交流。

 

就说这么多吧,感谢阅读。

 

4、简化版(去除令牌)

[此节添加于 2023 年 8 月 30 日]

 

由于之前重写的 OnDeactivated 方法中调用了基类方法,而基类方法中已经是注销当前类的对象的所有注册消息了:

WPF 消息传递简明教程

 

所以要么不调用基类方法,要么直接不重写此方法,本节选择后者(直接移除此重写)。

 

然后是注册消息的简化,本节是去除了 令牌 Token(前文称之为通道):

WPF 消息传递简明教程

 

自然地,发送的时候也可以去除令牌。

所以,除了保持 “继承 ObservableRecipient,构造函数中设置 IsActive=true” 之外,其余的可简化为如下代码(去除令牌):

#region 消息处理

/// <summary>
/// 注册消息接收  
/// </summary>
protected override void OnActivated()
{
    WeakReferenceMessenger.Default.Register<MainViewModel, MyMessage>(this, OnReceiveMessage);
}

/// <summary>
/// 收到消息时的处理方法
/// </summary>
/// <param name="recipient">接收者</param>
/// <param name="message">消息</param>
private void OnReceiveMessage(MainViewModel recipient, MyMessage message)
{
    //处理逻辑;
    Dispatcher.CurrentDispatcher.Invoke(() =>
    {
        //可能需要这样调度回 UI 线程;
    });
}

#endregion

//消息发送(一般在其它类中)
WeakReferenceMessenger.Default.Send(new MyMessage());

 

然后看看类库中 Register 方法的重载:

WPF 消息传递简明教程

 

可以看出关键的只需要 TMessage 就行了,也就是说接收者(或者称之为注册者) TRecipient 也是可以省略的,关于这一点,本次暂未研究,之后研究了再和大家分享。

 

 

原创文章,转载请注明: 转载自 独立观察员(dlgcy.com)

本文链接地址: [WPF 消息传递简明教程](https://dlgcy.com/toolkit-mvvm-message/)

关注微信公众号 独立观察员博客(DLGCY_BLOG) 第一时间获取最新文章

%title插图%num

发表评论