微软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.GenerateCommandGenerateViewModelGenerateProperty使用略有不同,后两个特性可以正常添加,GenerateCommand特性添加时,若没有安装DevExpress.Mvvm包,会有异常:未找到类型或命名空间

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

相关推荐
Xin_ye100861 小时前
第七章:进阶篇——事件监听、外部服务集成与性能优化
c#
z落落2 小时前
C# WinForm NModbus 串口通信+WinForm Modbus4 串口通信
开发语言·单片机·c#
CoderIsArt2 小时前
C#环境中部署MQTT客户端
开发语言·c#
CSDN_RTKLIB3 小时前
模型空间、布局控件、自定义块
c#
z落落3 小时前
C# WinForm TCP 服务器+WinForm TCP 客户端
服务器·tcp/ip·c#
csdn_aspnet3 小时前
C# 多个串口多个线程发送数据和接收数据
c#·串口·thread·com·serialport
吴可可12316 小时前
多段线局部约束缩放实现
c#
棉晗榜20 小时前
C# HttpClient配置具有tls指纹发起跟浏览器一样的请求解决反爬虫防护
开发语言·爬虫·c#
吴可可12320 小时前
在CAD中点击添加多段线顶点的方法与实现
c#