CommunityToolkit.MVVM

news2024/9/23 7:33:24

前言

MVVM工具包,以前名为 Microsoft.Toolkit.Mvvm 由 Microsoft 维护和发布,是 .NET Foundation 的一部分。

支持:.NET Standard 2.0、 .NET Standard 2.1 和 .NET 6(UI Framework 不可知,基本使用没有问题/编译特性用不了)

注:可以当做MvvmLight的替代品 大部分方法一样

安装:

安装:Nuget -> CommunityToolkit.MVVM

常规对象

ObservableObject:通知属性

第一种:基本通知属性

和MvvmLight一模一样

public partial class MainViewModel : ObservableObject
{
    // 1、基本通知属性
    private string _value;

    public string Value
    {
        get { return _value; }
        set
        {
            SetProperty(ref _value, value);
            //_value = value;
            //this.OnPropertyChanging();
        }
    }
}

第二种:直接通过实体返回 或者赋值

public partial class MainViewModel : ObservableObject
{
    UserEntity userEntity = new UserEntity();

    // 直接通过实体返回 或者赋值
    public string UserName
    {
        get { return userEntity.userName; }
        set
        {
            userEntity.userName = value;
            this.OnPropertyChanging(nameof(UserName));
    
            // 通过 SetProperty 给 Model 赋值
            SetProperty<UserEntity, string>(userEntity.userName, value, userEntity, (entity, v) => { entity.userName = v; });
        }
    }
}
public class UserEntity
{
    public string userName { get; set; }
    public int age { get; set; }
}

第三种:异步赋值

public partial class MainViewModel : ObservableObject
{
    private TaskNotifier<int> taskValue;

    public Task<int> TaskValue
    {
        get { return taskValue; }
        set
        {
            // 异步赋值 
            SetPropertyAndNotifyOnCompletion(ref taskValue, value);
        }
    }
    
    private void Refresh()
    {
        TaskValue = new Task<int>(() => { Thread.Sleep(3000); return 1000; });
    }
}

RelayCommand/RelayCommand<T>:绑定属性

和MvvmLight一模一样

 public RelayCommand BtnCommand { get; set; }
 public MainViewModel()
 {
     BtnCommand = new RelayCommand(()=>{ });
 }

Messenger:订阅

WeakReferenceMessenger(弱订阅)/StrongReferenceMessener(强订阅)

 public MainViewModel()
 {
     BtnCommand = new RelayCommand(BtnClick);

     // 消息订阅 Token 
     WeakReferenceMessenger.Default.Register<string, string>(this, "One", (obj, str) =>
     {
         (obj as MainViewModel).Value = str;
     });
     WeakReferenceMessenger.Default.Register<string, string>(this, "Two", (obj, str) =>
     {
         (obj as MainViewModel).Value = str;
     });
     // 释放
     WeakReferenceMessenger.Default.UnregisterAll(this);
 }

 private void BtnClick()
 {
     // 触发
     WeakReferenceMessenger.Default.Send<string, string>("One", "One");
     WeakReferenceMessenger.Default.Send<string, string>("Two", "Two");
 }

IOC:容器

默认这个工具包中没有IoC对象,建议使用 ServiceCollection

实例化IOC容器:

// 实例化 IOC容器 
static ServiceCollection service = new ServiceCollection();
public static IServiceProvider Service { get; private set; }

添加IOC容器:

service.AddSingleton<MainViewModel>();

Service = service.BuildServiceProvider();

使用IOC容器中的类:

App.Service.GetService<MainViewModel>();

释放IOC容器:

service.RemoveAll<MainViewModel>();

结合关闭当前界面,释放当前ioc容器:

MainViewModel:需要继承IDisposable,重写Dispose 方法:

public class MainViewModel : ObservableObject, IDisposable
{
    public void Dispose()
    {
        // 释放资源
    }
}

在APP.xaml(写IOC注入的类)中写清除方法:

   public static void Cleanup<T>() where T : IDisposable
   {
       Service.GetService<T>().Dispose();

       service.RemoveAll<T>();
   }

在窗体界面调用:

 protected override void OnClosed(EventArgs e)
 {
     base.OnClosed(e);
     App.Cleanup<MainViewModel>();
 }

扩展对象

特性

ObservableProperty:通知属性

[ObservableProperty]
public string name;

以上代码等同于:

private string name;

public string Name
{
    get { return name; }
    set { name = value; }
}

写法注意:一般都是小写,然后工具类中自动变为大写:abcNet --> AbcNet ; _abcNet --> AbcNet ; m_abcNet --> AbcNet

所以,就算字段是name,界面可以直接使用Name来赋值。

注意:当前类需要加partial修饰符,因为当写这个特性的时候,工具类会自动生成一个文件与此类绑定,必须加修饰符进行绑定:

处理当前修饰符特性字段的变化逻辑:
 // 如何处理这个字段特性的变化set逻辑/过程
 partial void OnNameChanged(string? oldValue, string newValue)
 {
     // 处理字段变化过程

 }

 partial void OnNameChanging(string? oldValue, string newValue)
 {
     // 当字段开始变化时执行

 }

NotifyPropertyChangedFor:

修改此属性的时候,通知指定属性

[ObservableProperty]
[NotifyPropertyChangedFor("FullName")] 
//NotifyPropertyChangedFor:修改此属性的时候,通知指定属性;
//当更新name的时候,也要更新FullName 
public string name;

// 页面绑定的是FullName 属性 ,
private string FullName { get => "xh" + name; }

ObservableValidator:验证

需要验证的类一般继承ObservableValidator,然后一般是写在Model层,不是ViewModel层

NotifyDataErrorInfo:这个特性必须加,否则不会校验,关键的校验特性

其他特性和普通特性一样,没有变化

 [ObservableProperty]
 [NotifyDataErrorInfo] //NotifyDataErrorInfo:关键的校验特性
 [Required(ErrorMessage = "必填")]// 必填项目
 [MinLength(1)] // 最小长度
 private string inputValue = "123";

NotifyPropertyChangedRecipients:广播通知

[NotifyPropertyChangedRecipients]
class A : ObservableRecipient
{
    public string Name { get; set; }
    // 广播信息
    protected override void Broadcast<T>(T oldValue, T newValue, string? propertyName)
    {
        base.Broadcast(oldValue, newValue, propertyName);
    }
}

RelayCommand:命令

 [RelayCommand] 
// RelayCommand:自动生成相关内容,可以直接绑定 自动生成name+Command
 private void DoButton()
 {

 }

界面使用:

<Button Content="Btn" Command="{Binding DoButtonCommand}" />

AsyncRelayCommand

异步绑定事件:

public AsyncRelayCommand AsyncButtonCommand { get; set; }
public MainViewModel()
{
    AsyncButtonCommand = new AsyncRelayCommand(AsyncButtonClick);
}
// 异步执行绑定
private Task AsyncButtonClick()
{
 return Task.Run(() => { });
}
// 以上相当于:
private void BtnClick()
{
 Task.Run(() => { });
}

Message相关/ ObservableRecipient

需要继承类:ObservableRecipient,实现接口IRecipient<in TMessage>

在构造函数中,开启消息接收this.IsActive = true;

核心代码如下:

private void BtnClick()
{
 // 触发
 WeakReferenceMessenger.Default.Send<string>("Hello");
}
// 接受
public void Receive(string message)
{
 // message == Hello
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2050790.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言-写一函数,实现两个字符串的比较。即自己写一个strcmp函数,函数原型为 int strcmp(char *pl,char *p2);

题目要求&#xff1a; 17.写一函数,实现两个字符串的比较。即自己写一个strcmp函数,函数原型为 int strcmp(char *pl,char *p2); 设p1指向字符串s1&#xff0c;p2指向字符串s2。要求当s1s2时,返回值为0;若s1≠s2,返回它们二者第1个不同字符的 ASCI1码差值(如"BOY"与…

微信小程序--28(npm包)

目录 一、小程序对npm的支持与限制&#xff0c; 二、什么是Vant Weapp 三、安装Vant组件库 &#xff08;一&#xff09;通过npm安装 &#xff08;二&#xff09;构建npm包 &#xff08;三&#xff09;修改 app.json 一、小程序对npm的支持与限制&#xff0c; 小程序已经支…

STM32标准库学习笔记-6.定时器-输入捕获

参考教程&#xff1a;【STM32入门教程-2023版 细致讲解 中文字幕】 定时器输入捕获 IC&#xff08;Input Capture&#xff09;输入捕获输入捕获模式下&#xff0c;当通道输入引脚出现指定电平跳变时&#xff0c;当前CNT的值将被锁存到CCR中&#xff0c;可用于测量PWM波形的频率…

一起看下halcon逻辑结构

halcon中结构包括顺序结构、分支结构、循环结构三种&#xff0c;不存在跳转的结构语句。 注意cntinue:结束本次循环,break跳出本次循环 选择结构&#xff1a; 1.if…end if 2.if…else…end if 3.if…elseif…elseif…end if 循环结构&#xff1a; 1.while()…endwhile …

<STC32G12K128入门第十二步>STC32G低功耗设计

前言 本文主要讲STC32G的低功耗设计,包括软件设计和硬件设计。其中有软件有一个问题当时困扰了我几个小时。都是精华 一、STC32G低功耗硬件设计 STC32G的硬件设计思路,最基本的就是需要考虑使用低功耗的硬件,比如ldo或者dc-dc需要考虑他的静态功耗,最好选择ua级别的。然…

【Hot100】LeetCode—206. 反转链表

目录 1- 思路递归法 2- 实现⭐206. 反转链表——题解思路 3- ACM 实现 原题连接&#xff1a;206. 反转链表 1- 思路 递归法 递归三部曲 ①终止条件&#xff1a;遇到 head null || head.nextnull 的时候②递归逻辑&#xff1a;定义 cur &#xff0c;cur 执行递归逻辑&#xff…

<数据集>商品条形码识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;3748张 标注数量(xml文件个数)&#xff1a;3748 标注数量(txt文件个数)&#xff1a;3748 标注类别数&#xff1a;1 标注类别名称&#xff1a;[Barcode] 序号类别名称图片数框数1Barcode37484086 使用标注工具&am…

4. 寻找两个正序数组的中位数(困难)

4. 寻找两个正序数组的中位数 1. 题目描述2.详细题解3.代码实现3.1 Python3.2 Java 1. 题目描述 题目中转&#xff1a;4. 寻找两个正序数组的中位数 2.详细题解 两个有序数组&#xff0c;寻找二者的中位数&#xff0c;最直观的方法是先归并这两个数组为一个有序数组&#x…

SQLite数据库的创建和升级

SQLite数据库的创建和升级 在刚开始接触Android的时候&#xff0c;我甚至都不敢相信&#xff0c;Android系统竟然是内置了数据库的&#xff01;好吧&#xff0c;是我太孤陋寡闻了。SQLite是一款轻量级的关系型数据库&#xff0c;它的运算速度非常快&#xff0c;占用资源很少&a…

开源通用验证码识别OCR —— DdddOcr 源码赏析(一)

文章目录 [toc] 前言DdddOcr环境准备安装DdddOcr使用示例 源码分析实例化DdddOcr实例化过程 分类识别分类识别过程 未完待续 前言 DdddOcr 源码赏析 DdddOcr DdddOcr是开源的通用验证码识别OCR 官方传送门 环境准备 安装DdddOcr pip install ddddocr使用示例 示例图片如…

Datawhale X 魔搭 AI夏令营第四期 魔搭-AIGC方向全过程笔记

task1: 传送门 task2&#xff1a; 传送门 task3: 传送门 目录 Task1 赛题内容 可图Kolors-LoRA风格故事挑战赛 baseline要点讲解(请配合Datawhale速通教程食用) Step1 设置算例及比赛账号的报名和授权 Step2 进行赛事报名并创建PAI实例 Step3 执行baseline Step4…

软件架构:架构模式、特征及实践指南-读书笔记(1)

第二章 架构思维 2.1 架构与设计 为了使架构落地&#xff0c;必须打破阻碍在架构师和开发人员之间的所有障碍&#xff0c;从而使架构师和开发团队之间形成双向的强关联。如图2-3所示&#xff0c;架构师和开发人员必须在同一个虚拟团队中才能使架构落地。该模型不仅促进了架构师…

关于使用conda安装opencv-python失败的解决方法

当你想使用conda环境安装opencv-python时&#xff0c;会弹出&#xff1a; conda install opencv-python Collecting package metadata (current_repodata.json): done Solving environment: failed with initial frozen solve. Retrying with flexible solve. Collecting packa…

【网络】网络基础概念背景TCP/IP 五层模型跨网络传输详解

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;计算机网络原理_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1.计算机网络发展 1.1 独立模式 1.2 网络互联 1.3 局域网 LAN 1.4 广域网 WAN 2.协议 2.1 初识协议 2.2 协议分层 2…

应急响应:挖矿木马-实战 案例一.【Linux 系统-排查和删除】

什么是挖矿木马 挖矿木马是一种恶意软件&#xff0c;它在未经用户许可的情况下&#xff0c;利用用户的计算资源来挖掘加密货币&#xff0c;从而为攻击者带来非法收益。这类软件通常通过多种手段传播&#xff0c;例如利用系统漏洞、弱密码爆破、伪装正常软件等方法感染目标设备…

TI官网下载芯片原理图文件和封装文件导入Altium Designer 21.0.9

1、TI文件下载以 UCC27614为例 打开TI官网直接找到元器件资料界面 在设计与开发栏中找到封装模型文件下载 确认封装 选择封装导出的目标软件–AD 2、文件导入AD软件中 解压压缩包找到项目文件使用AD打开 导入AD输出芯片封装 打开UL_Import.pas然后点击Run 出现UL Import 选择…

20240818 每日AI必读资讯

3人干翻谷歌&#xff01;免费学术搜索比谷歌学术相关性高5倍&#xff0c;已获YC投资 - 三人团队打造的学术搜索引擎&#xff1a;Lumina - 目前已处理了超30万次查询&#xff0c;支持24种语言 - 号称搜索结果相关性平均比谷歌学术高5倍&#xff0c;能搜索超1亿个研究对象&…

类和对象(下)(1)

类和对象&#xff08;下&#xff09; 再探构造函数 我们之前在实现构造函数的时候&#xff0c;初始化成员变量使用的方式都是在函数体内进行赋值&#xff0c;其实构造函数初始化成员变量还有一种方式&#xff1a;初始化列表。 初始化列表不只是为了写得方便&#xff0c;还能解…