微软CommunityToolkit.Mvvm和DevExpress中GenerateViewModel使用
发布时间:2026/9/1 16:21:39 作者:尧图编辑部 阅读量:1,286

注意Blazor需要使用的ViewModel需要提前进行注册//在Program.cs中 builder.Services.AddScopedViewModel();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//第一种 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控制按钮是否可用;//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.定义消息实现ValueChangedMessageT为消息内容2.VM订阅或发布消息需继承ObservableRecipient 实现IRecipientT构造函数里OnActivated()完成弱引用注册ReceiveT msg{//消息存放在msg.Value中}方法即回调获取发布的消息/ 通过订阅WeakReferenceMessenger.Default.Register(this, (recipient, msg) {//消息存放在msg.Value中}3.发布消息Messenger.Default.Send或WeakReferenceMessenger.Default.Send1.1 异常记录1.控件和ViewModel双向绑定若是使用嵌套属性绑定更新存在问题控件绑定Tenant.Name当Tenant更新时控件内容不变//处理方式 //1.实体 public partial class Tenant:ObservableObject { public int Id { get; set; } [ObservableProperty] private string name string.Empty; [ObservableProperty] private string sex 男; [ObservableProperty] private int age; [ObservableProperty] private decimal rent; [ObservableProperty] private DateTime startDate DateTime.Now; [ObservableProperty] private DateTime? endDate; //public string Name { get; set; } string.Empty; //public string Sex { get; set; } 男; //public int Age { get; set; } //public decimal Rent { get; set; } //public DateTime StartDate { get; set; } DateTime.Now; //public DateTime? EndDate { get; set; } } //2.ViewModel开始使用嵌套属性 //3.控件绑定数据 txt_Name.DataBindings.Add(nameof(txt_Name.Text), FViewModel, Tenant.Name, false, DataSourceUpdateMode.OnPropertyChanged);2.Messenger使用时使用WeakReferenceMessenger对象发布消息ViewModel中的Receive可以获得消息Messenger发布获取不到经过测试发现Messenger的命名空间是DevExpress.Mvvm而不是CommunityToolkit.Mvvm.ComponentModel当前包中只有IMessenger3.在Blazor中使用Messenger时界面中可使用WeakReferenceMessenger.Default.Send(new EditTenantMessage(aTenant))ViewModel中可使用Messenger.Send(new EditTenantMessage(tenant))注意构造函数中OnActivated()2 DevExpress:GenerateViewModelDevExpress 对标微软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.GetServiceT()获取 DX 内置服务IDataErrorInfo(System.ComponentModel.DataAnnotations): [Required(ErrorMessage )] [StringLength(20, ErrorMessage 最多20字符)] [Range(1,100, ErrorMessage 年龄必须1‑100)] 5.Messenger通信注意需要先订阅后发布这样才能获取到信息//先执行,viewmodel使用this也行 Messenger.Default.Register信息(viewmodel, m {//针对信息的处理m信息对象}); //后执行 Messenger.Default.Send(信息); //注意最后要取消订阅 Messenger.Default.Unregister(viewModel); 6.winform程序需要特殊组件MVVMContextvoid InitializeBindings() { // Initialize bindings for EditView //mvvmContext1.ViewModelType typeof(EditViewModel); var bFluent mvvmContext1.OfTypeEditViewModel(); //fViewModel bFluent.ViewModel; fViewModel new EditViewModel(); mvvmContext1.SetViewModel(typeof(EditViewModel), fViewModel); // 订阅信息 Messenger.Default.RegisterTenant(fViewModel, m { fViewModel.Tenant m; fViewModel.Title $编辑租户:{m.Name}; }); //Messenger.Default.RegisterTenant(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.控制按钮IsEnableCanExecute只针对桌面程序//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通信注意需要先订阅后发布这样才能获取到信息3.Messenger通信不能用于Blazor项目其依赖于WindowsBase会抛出TypeLoadException3 总结1.CommunityToolkit.Mvvm微软官方维护不依赖其他任何第三方GenerateViewModel依赖Dev2.CommunityToolkit.Mvvm某些组件需要继承或实现GenerateViewModel主要使用特性3.针对不同的平台均需要进行不同的实现但是GenerateViewModel某些组件依赖于特定UI4.易用性方面CommunityToolkit.Mvvm中组件绑定嵌套属性时会存在界面刷新问题GenerateViewModel不存在此问题综上若要完全通用减少第三方依赖建议使用CommunityToolkit.Mvvm若可以依赖Dev建议使用GenerateViewModel。