文章目录
- 专栏和Gitee仓库
- 前言
- 消息订阅
- 最简单的案例
- 简单用例
- 父组件订阅
- 子组件回调
- 结果
- 消息订阅机制
- 消息token是A还是B?
- 传递消息的载体。
- 双重token
- 重复订阅问题
- 结论
专栏和Gitee仓库
WPF仿网易云 Gitee仓库
WPF仿网易云 CSDN博客专栏
前言
上一篇文章中,我们简单讲解了一下父子通讯的逻辑。父子通讯是强绑定逻辑。这里我们将讲解消息订阅通讯的方式。消息订阅一般用于[页]和[页]之间通讯。
消息订阅
WPF消息订阅一共有两种方案,一个是Prism的方案,一个是CommunityToolkit.Mvvm的方案。
WPF Prims框架详解
WPF CommunityToolkit.Mvvm Messenger通讯
这里我们使用使用CommunityToolkit.Mvvm。使用Prism的也可以。
最简单的案例
简单用例
不了解CommunityToolkit.Mvvm的可以看这个
WPF CommunityToolkit.Mvvm Messenger通讯
这里用到了record,不了解的可以看这个文章。当然也可以用class
博客园 C# – Record, Class, Struct
父组件订阅
namespace BlankApp1.Views
{/// <summary>/// Interaction logic for MainWindow.xaml/// </summary>public partial class MainWindow : Window{public record MainWindowMessage(string msg);public MainWindowViewModel ViewModel { get; set; }public MainWindow(){......其它代码InitializeComponent();//订阅MainWindowMessage的对象数据WeakReferenceMessenger.Default.Register<MainWindowMessage>(this,MessageRecieve);//也可以取消订阅,但是一般不用//WeakReferenceMessenger.Default.Unregister<MainWindowMessage>(this);}private void MessageRecieve(object recipient, MainWindowMessage message){Debug.WriteLine("接受到消息"+message.msg);}}
}
子组件回调
MiniWindow = new RelayCommand(() => {//其它代码逻辑,不重要......//发送订阅消息WeakReferenceMessenger.Default.Send(new MainWindowMessage("缩小窗口"));
});
结果
消息订阅机制
我们模拟一个最简单的消息订阅场景。ViewA给ViewB推送消息。
消息token是A还是B?
我们推送订阅消息,需要用到Key去推送订阅。那么用的是Key_A还是Key_B呢。
这个时候,我们就要想到推送开发时候的流程了。我们一般开发都是先暴露,再使用的代码开发流程。所以我们一般是先想ViewB能做什么,先写好订阅,再写推送逻辑的。而且一般是一次订阅,多次推送。可以ViewA推送ViewB,也可以ViewC推送ViewB,ViewD推送ViewB。
所以结论:用到token是订阅者的token。是token_B
。
传递消息的载体。
我们传递消息,需要考虑到载体的问题。我们为了简化代码,一般消息载体都是用string字符串作为载体。使用Json格式传递。通过序列化和反序列化来进行区别。
这里我推荐使用Newtonsoft。这里不展开说明
双重token
CommunityToolkit.Mvvm8.1 消息通知(4)
【CommunityToolkit.Mvvm】Messenger 信使
如果是单一Token,只能做到View的订阅。如果是双重Token,我们可以做到View的某个函数的订阅。极大得增强了函数的复用性。这里我建议使用Enum
枚举类型作为token
/// <summary>
/// 消息订阅载体
/// </summary>
/// <param name="Msg"></param>
public record MainWindowMessage(string Msg);//声明enum枚举类型
public enum MainWindowMessageToken { Test1, Test2 }//双重token订阅
WeakReferenceMessenger.Default.Register<MainWindowMessage, string>(this, MainWindowMessageToken.Test1.ToString(), MessageRecieve);//使用token双重推送
WeakReferenceMessenger.Default.Send(new MainWindowMessage("缩小窗口"), MainWindowMessageToken.Test1.ToString());
重复订阅问题
如果重复订阅,会主动抛出异常
结论
我们消息流已经基本解决了。
- 强关联:父子通讯:组件化通讯
- 弱关联:消息订阅:页与页,窗口与窗口
我们最后的信息流控制就是IOC容器了,IOC容器解决了之后,我们已经将WPF完全解耦,所有复杂的WPF问题都可以变成简单的单一问题。