微软CommunityToolkit.Mvvm和DevExpress中GenerateViewModel使用

1 微软:CommunityToolkit.Mvvm

平台无关:无界面,专门给 WPF、WinForms、UWP、WinUI、MAUI、Avalonia 等桌面 / XAML 框架做 MVVM 分层开发

微软官方维护的MVVM架构轻量级库

使用方式:

​ 1.partial修饰ViewModel继承类ObservableObject,需要Nuget包:Microsoft.Toolkit.Mvvm;

​ 2.属性字段(eg:private string name;)使用标签ObservableProperty,编译自动生成完整属性+通知;可与NotifyCanExecuteChangedFor(nameof(AddCommand))标签结合使用,属性变化,通知命令刷新 CanExecute 状态,控制按钮 IsEnabled,与之相似的还有NotifyPropertyChangedFor,属性变化,通知其他属性刷新 UI;

c# 复制代码
//第一种
date_End.DataBindings.Add(nameof(date_End.EditValue), FViewModel, nameof(FViewModel.Tenant.EndDate), false, DataSourceUpdateMode.OnPropertyChanged);
//第二种
date_End.DataBindings.Add(new Binding(nameof(date_End.EditValue), FViewModel.Tenant, nameof(FViewModel.Tenant.EndDate), false, DataSourceUpdateMode.OnPropertyChanged));

​ 3.方法(eg:Save())使用标签RelayCommand,编译自动生成命令(eg:SaveCommand);

​ 4.CanExecute 控制按钮是否可用;

c# 复制代码
//ViewModel
//1.定义控制IsEnabled的属性;
private bool CanAdd => !string.IsNullOrEmpty(Name) && Age >= 18 && Age <= 70 && Rent >= 0 && EndDate >= StartDate;
//2.命令特性中设置CanExecute
[RelayCommand(CanExecute = nameof(CanAdd))]
public void Add(){......}
//3.涉及到的属性添加
[NotifyCanExecuteChangedFor(nameof(AddCommand))]

//项目中
//4.进行相关绑定
//添加按钮是否可点击CanExecute
FViewModel.AddCommand.CanExecuteChanged += (s, e) => btn_Add.Enabled = FViewModel.AddCommand.CanExecute(null);
btn_Add.Enabled = FViewModel.AddCommand.CanExecute(null);

​ 5.VM之间/VM和界面之间可通过内置消息总线 Messenger(组件解耦)进行通信(1.定义消息实现ValueChangedMessage,T为消息内容;2.VM订阅或发布消息,需继承 ObservableRecipient + 实现 IRecipient<T>,构造函数里 OnActivated() 完成弱引用注册(Receive(T msg){//消息存放在msg.Value中} 方法即回调,获取发布的消息)/ 通过订阅WeakReferenceMessenger.Default.Register(this, (recipient, msg) =>{//消息存放在msg.Value中});3.发布消息:Messenger.Default.Send或WeakReferenceMessenger.Default.Send;

1.1 异常记录

1.控件和ViewModel双向绑定,若是使用嵌套属性绑定,更新存在问题:控件绑定Tenant.Name,当Tenant更新时,控件内容不变;

2.Messenger使用时,使用WeakReferenceMessenger对象发布消息,ViewModel中的Receive可以获得消息,Messenger发布获取不到,经过测试发现,Messenger的命名空间是DevExpress.Mvvm,当前包中只有IMessenger;

2 DevExpress:GenerateViewModel

DevExpress 对标微软 CommunityToolkit.Mvvm 源生成器技术的新一代 MVVM 实现

发展:继承ViewModelBase ➡ POCOViewModel(项目创建默认,中间类动态生成,异常追踪困难)➡ GenerateViewModel(中间类编译生成,性能更好)

使用方式:

​ 1.partial 分部类,打上类级特性GenerateViewModel,需要Nuget包:DevExpress.Mvvm.CodeGenerators(当前最新版本:22.1.1,独立开源,与Dev解耦);

​ 2.字段标记GenerateProperty,编译自动生成属性+INotifyPropertyChanged通知,注意首字母小写,否则编译异常;

​ 3.方法标记GenerateCommand,若需要异步命令GenerateCommand(AllowAsync = true),自动生成命令;

​ 4.支持自动实现 IDataErrorInfo 校验(WPF可以直接使用)、父子 ViewModel 关联(GenerateViewModel(ImplementISupportParentViewModel = false))、DX 服务注入接口(ISupportServices接口,有了这个接口,你的 ViewModel 就可以调用扩展方法:this.GetService<T>() 获取 DX 内置服务);

c# 复制代码
IDataErrorInfo(System.ComponentModel.DataAnnotations):
[Required(ErrorMessage = "")]
[StringLength(20, ErrorMessage = "最多20字符")]
[Range(1,100, ErrorMessage = "年龄必须1‑100")]

​ 5.Messenger通信,注意需要先订阅,后发布,这样才能获取到信息;

c# 复制代码
//先执行,viewmodel使用this也行
Messenger.Default.Register<信息>(viewmodel, m => {//针对信息的处理,m=信息对象});
//后执行
Messenger.Default.Send(信息);
//注意,最后要取消订阅
Messenger.Default.Unregister(viewModel);

​ 6.winform程序需要特殊组件:MVVMContext

c# 复制代码
void InitializeBindings()
{
  // Initialize bindings for EditView
  //mvvmContext1.ViewModelType = typeof(EditViewModel);
  var bFluent = mvvmContext1.OfType<EditViewModel>();
  //fViewModel = bFluent.ViewModel;
  fViewModel = new EditViewModel();
  mvvmContext1.SetViewModel(typeof(EditViewModel), fViewModel);

  // 订阅信息
  Messenger.Default.Register<Tenant>(fViewModel, m =>
  {
    fViewModel.Tenant = m;
    fViewModel.Title = $"编辑租户:{m.Name}";
  });
  //Messenger.Default.Register<Tenant>(fViewModel, m => fViewModel.LoadTenant(m));

  bFluent.SetBinding(this, view => view.Text, x => x.Title);
  bFluent.SetBinding(lbl_Message, l => l.Text, x => x.Message);
  bFluent.SetBinding(txt_Name, t => t.EditValue, x => x.Tenant.Name);
  bFluent.SetBinding(cmb_Sex, c => c.EditValue, x => x.Tenant.Sex);
  bFluent.SetBinding(txt_Age, t => t.EditValue, x => x.Tenant.Age);
  bFluent.SetBinding(txt_Rent, t => t.EditValue, x => x.Tenant.Rent);
  bFluent.SetBinding(date_Start, d => d.EditValue, x => x.Tenant.StartDate);
  bFluent.SetBinding(date_End, d => d.EditValue, x => x.Tenant.EndDate);
  bFluent.BindCommand(btn_Save, x => x.Save);
}

​ 7.控制按钮IsEnable(CanExecute,只针对桌面程序)

c# 复制代码
//1.按钮点击命令
[GenerateCommand]
public void Add() {
  ......
}
//2.按钮事件是否可用
public bool CanAdd() => !string.IsNullOrEmpty(SearchText);
//3.相关属性变更事件
public void OnSearchTextChanged() => AddCommand.RaiseCanExecuteChanged();

2.1 异常记录

1.GenerateCommand和GenerateViewModel、GenerateProperty使用略有不同,后两个特性可以正常添加,GenerateCommand特性添加时,若没有安装DevExpress.Mvvm包,会有异常:未找到类型或命名空间

2.Messenger通信,注意需要先订阅,后发布,这样才能获取到信息;

相关推荐
Leinwin12 小时前
Copilot Studio 实战:多模型选择、GitHub Copilot harness 计费与 Copilot Credits 额度管理
开发语言·c#
FuckPatience12 小时前
C# Winform 使用Label循环显示闪烁
开发语言·c#
念何架构之路13 小时前
OpenTelemetry核心概念
后端·目标跟踪·golang·c#·linq
开开心心就好13 小时前
电脑语音实时转文字工具,会议记录很省事
运维·服务器·前端·c#·ocr·perl·1024程序员节
波力海苔夹心脆67513 小时前
C# 固高 GTS 运动控制卡入门:伺服上下电、Jog 点动与二维插补(WinForms 实战)
服务器·开发语言·c#·运动控制·伺服电机·winforms·固高
何以解忧唯有撸码20 小时前
c# + YOLODotNet+OpenCVSharp 实现物品轨迹追踪
计算机视觉·c#·winform·yolov8·opencvsharp
阿松爱学习1 天前
【Unity开发】局部区域截图功能实现
unity·c#
zhanghaha13141 天前
C# 系列教程_1 基础语法篇(面向新手系统教程)
开发语言·c#
昂好的day1 天前
固高运动控制卡实战(下):点位运动与直线/圆弧插补 API 详解
开发语言·c#
淡海水1 天前
08-02-优化-LINQ与函数式编程的GC代价
unity·c#·.netcore·linq·gc