首页 > 其他分享 >MAUI新生2.4-数据绑定和MVVM:MVVM的消息机制

MAUI新生2.4-数据绑定和MVVM:MVVM的消息机制

时间:2022-12-02 00:22:59浏览次数:42  
标签:订阅 MVVM Default 消息 MAUI 2.4 public 信使 View

当两个对象之间需要建立松耦合关系时,特别适合使用消息机制。如ViewModel需要控制View进行某些操作时,如弹出对话框、播放动画,由于ViewModel对View是无感的,我们不能在ViewModel中去操作View,否则会造成ViewModel对View的依赖。另外,ViewModel层之间、以及View页面之间,也可能需要通过消息传递来完成一些交互。CommunityToolkit.Mvvm提供了比较完善的消息机制,以下内容主要介绍它的使用。使用前,需安装nuget包:CommunityToolkit.Mvvm。

 

一、基本过程:如下图所示,一个消息的收发,或者叫订阅与发布,主要有三个过程:

1、创建信使和消息类型,信使的作用:一是起到消息发布者与订阅者的桥梁作用;二是携带消息。在代码层面,信使是派生自ValueChangedMessage<T>或RequestMessage<T>的普通类,其中泛型T为消息的类型。

2、订阅消息(Register),消息订阅者通过【WeakReferenceMessenger.Default.Register<T>(this,(r,m)=>{});】订阅消息,其中泛型T为信使类,只要这个信使类被发布,它就能收到通知和消息。【(r,m)=>{}】为订阅者收到通知后的执行逻辑,是一个Lambda函数,也有叫事件处理者Handler。其中参数 r 指消息订阅所在的这个对象,通过this传入,通过 r 可以在Lambda函数中引用其它成员;参数 m 就是信使携带的消息对象。

3、发布消息(Send),消息发布者通过【WeakReferenceMessenger.Default.Send(new一个信息类对象)】发布消息。

 

 

 

二、在何处执行订阅和发布:如上图,虽然知道了订阅和发布的代码,但它们应该在何处执行?

1、在哪里执行消息订阅:View和ViewModel中,都可以订阅消息。其中View在构造函数中订阅。而ViewModel,Mvvm为我们提供了ObservableRecipient基类(ObservableRecipient派生自ObservableObject),继承它后,有两个重写方法OnActivated和OnDeactivated,消息订阅写在OnActivated方法中,消息注销写在OnDeactivated方法中。

2、在哪里发布消息:任何可执行方法中,都可以发布消息。在Mvvm开发模式中,我们一般在命令中发布消息。

 

 

 

三、案例一:ViewModel通过一个命令发布消息给View,View收到消息通知后,通过弹窗显示消息

1、创建信使,消息类型为string,HiMessenger.cs

//信使类为HiMessenger,消息类型为string
public class HiMessenger: ValueChangedMessage<string> 
{
    public HiMessenger(string value):base(value) //创建信使对象时,通过构造函数初始化消息
    {
    }
}

 

2、ViewModel中发布消息,MainPageViewModel.cs

public partial class MainPageViewModel:ObservableRecipient
{
    protected override void OnActivated()
    {
        base.OnActivated();//在OnActivated方法中订阅消息,本例中不需要
    }

    [RelayCommand]
    private void SendHiMessage()
    {
        WeakReferenceMessenger.Default.Send(new HiMessenger("Hi,I'm functionMC.I come from China."));//发布消息
    }
}

 

3、View的后台代码订阅消息并在回调中弹窗显示消息,View的XAML中绑定SendHiMessageCommand命令,MainPage.xaml和MainPage.xaml.cs

//前台代码MainPage.xaml
<ContentPage
    ......
    BindingContext="{Binding MainPageViewModel,Source={StaticResource ServiceLocator}}">

    <VerticalStackLayout>
        <Button Text="发送信息" Command="{Binding SendHiMessageCommand}"></Button>
    </VerticalStackLayout>

</ContentPage>

//后台代码MainPage.xaml.cs
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
        //订阅消息,回调中执行ShowHiMessage函数,并传入接收到的消息
        WeakReferenceMessenger.Default.Register<HiMessenger>(this, async (r,m) =>
        {
            await ShowHiMessage(m.Value);
        });
    }
    public async Task ShowHiMessage(string message)
    {
        await DisplayAlert("Alert",message,"OK");//弹窗显示消息
    }
}

 

 

 

四、案例二:AddName页面,添加姓名;NameList页面,显示姓名列表。AddNameViewModel通过消息机制,将绑定属性Name发送给NameListViewModel,NameListViewModel收到信息后,添加到NameList集合。

//①创建信使类,NameMessenger.cs=====================================================================
public class NameMessenger : ValueChangedMessage<string>
{
    public NameMessenger(string value) : base(value) 
    {
    }
}

//②订阅信息,NameListViewModel.cs=================================================================== public partial class NameListViewModel:ObservableRecipient { protected override void OnActivated() { //订阅信使NameMessenger,并将收到的信息添加到NameList集合中 WeakReferenceMessenger.Default.Register<NameListViewModel, NameMessenger>(this, (r,m) => { r.NameList.Add(m.Value); }); }
//绑定姓名列表页面的ListView控件显示姓名列表 [ObservableProperty] private ObservableCollection<string> nameList; }
//③发布信息,AddNameViewModel.cs===================================================================== public partial class AddNameViewModel:ObservableRecipient { //绑定View层的输入姓名 [ObservableProperty] private string name; //绑定View层的按钮执行添加命令 [RelayCommand] private void AddName() { //在命令中,发送信使NameMessenger,携带信息Name WeakReferenceMessenger.Default.Send(new NameMessenger(Name)); } } //View层略

 

 

 

五、其它知识点

1、传递的消息类型可以用复杂类型吗?可以,直接在信息类的泛型参数<T>中指定

 

2、消息发布者发布消息后,可以收到消息订阅者传回的信息吗?可以!如代码所示:

//以下信使类、消息类、ViewMode类,均为案例,按实际需求替换

//信使类继承自RequestMessage<T>
public class CurrentUserMessenger : RequestMessage<User>{}

//消息订阅者使用m.Reply返回信息
WeakReferenceMessenger.Default.Register<UserSenderViewModel,CurrentUserMessenger>(this,(r,m)=>m.Reply(r.UserName));

//消息发布者接收返回值
UserName = WeakReferenceMessenger.Default.Send<CurrentUserMessenger>();

 

3、WeakRefereceMessenger和StrongReferenceMessenger的区别?

Toolkit.Mvvm除了提供WeakRefereceMessenger(消息中心)之外,还提供了StrongReferenceMessenger。两者区别在于使用Weak...,系统会自动进行垃圾回收,防止内存泄漏;而Strong...需要手动注销消息订阅者,由于不需要启用自动回收机制,所以性能会好一点,但如果忘记注销,就容易引起内存泄漏,使用开发中,推荐使用Weak...。注销方式如下:

StrongReferenceMessenger.Default.Unregister<LoggedInUserChangedMessage>(this);//注销当前对象订阅的指定消息
StrongReferenceMessenger.Default.UnregisterAll(this);//注销当前对象订阅的所有消息

 

标签:订阅,MVVM,Default,消息,MAUI,2.4,public,信使,View
From: https://www.cnblogs.com/functionMC/p/16943224.html

相关文章

  • 快速绘制流程图「GitHub 热点速览 v.22.47」
    画流程图一直是研发的一个难题,如何画得通俗易懂已经够让人头疼了,还要美观大方。用d2的语法描述下流程,d2会自动帮你生成一张配色极佳的流程图。说到研发的选择,本周特推......
  • 2022.11.28-12.4 训练小记
    2022.11.28-12.4训练小记UVA12620FibonacciSum斐波那契数列在取模意义下是有循环节的(具体计算以后补),一个结论是在模\(p\)的意义下,循环节的大小不会大于\(6p\)。......
  • ansible2.4安装和体验
    欢迎访问我的GitHub这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos关于ansibleansible是常用的开源配置管理工具,简单易用,可以高效......
  • Linux高级-2.4在pycharm中使用vim编辑器-笔记
    如果没有Linux系统,可以在windows系统中利用pycharm的JetBrainsPlugins插件模拟使用vim。1.基本使用激活码BIG3CLIK6F-eyJsaWNlbnNlSWQiOiJCSUczQ0xJSzZGIiwibGljZW5zZWVOY......
  • 安卓设计模式演变之经典三层模型(MVC/MVP/MVVM)
    转载请标明出处!先看代码demo再回看文章效果最佳!目录​​一mvc​​​​1.1概述​​​​1.2 作用流程​​​​1.3 现状​​​​1.4致命弱点/缺点:​​​​1.5 代码Demo​......
  • 集WIFI、蓝牙连接的2.4寸串口屏智能烤箱应用方案
    近年来由于烹饪潮的持续风靡,烹饪行业正展现出强大的市场潜力。中国饮食文化源远流长,烹调技艺各具风韵,其中,煎、烤、炸类美食广受人们的欢迎。酥香松脆的煎烤美食,能够让身体......
  • MVVM教程(一):MVVM简介与准备工作
    如果你对MVVM的概念还是不了解,可以参看下面链接:​​​http://baike.baidu.com/view/3507915.htm​​我们以WPF+MVVM的本地桌面程序为背景,这样一来我们可以不去操心服务器那......
  • WPF_MVVM框架(5)
    1.NuGet引用MVVM框架包引入该框架包之后,默认会在目录下创建ViewModel层的示例代码2.第二步,通过在MainViewModel中创建一些业务代码,将其与MainWindow.xaml通过......
  • SpringBoot 2.4.0版本后解决跨域问题
    packagecom.atguigu.gulimall.gateway.config;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;impor......
  • WPF中实现MVVM
    MVVM(Model-View-ViewModel):Model指的是后台传递的数据,View指的是所看到的页面。ViewModel是mvvm模式的核心,它是连接view和model的桥梁。它有两个方向:一是将模型转化成视......