编辑
2026-01-22
C#
00
请注意,本文编写于 58 天前,最后修改于 58 天前,其中某些信息可能已经过时。

目录

源生成器实现属性通知
AsyncRelayCommand
取消任务
希望通知另一个属性
通知中继指令更新其可用状态
验证属性的值是否有效
为生成的属性添加特性
希望在属性值发生变化后执行额外的逻辑
消息中继/事件总线/发布-订阅

源生成器实现属性通知

C#
public partial class ViewModel : ObservableObject { [ObservableProperty] private string name; private bool CanSubmit() => !string.IsNullOrEmpty(name); [RelayCommand(CanExecute = nameof(CanSubmit))] private void Submit() { Debug.WriteLine($"Name: {name}"); } }

AsyncRelayCommand

C#
partial class MainViewModel : ObservableValidator { [ObservableProperty] private string name = ""; private bool CanSubmit() => !string.IsNullOrEmpty(Name); [RelayCommand(CanExecute = nameof(CanSubmit))] private async Task SubmitAsync() { await Task.Delay(1000); } }

取消任务

C#
[RelayCommand(CanExecute = nameof(CanSubmit), IncludeCancelCommand = true)] private async Task SubmitAsync(CancellationToken token) { try { await Task.Delay(2000, token); } catch (OperationCanceledException) { } }

希望通知另一个属性

C#
public partial class MainViewModel : ObservableObject { [ObservableProperty] [NotifyPropertyChangedFor(nameof(FullName))] //支持传入多个属性的名称 private string firstName = ""; //setter 中会生成形如 OnPropertyChanged("FullName") 的代码 public string FullName => firstName + " " + lastName; }

通知中继指令更新其可用状态

C#
public partial class MainViewModel : ObservableObject { [ObservableProperty] [NotifyCanExecuteChangedFor(nameof(FooCommand))] //支持传入多个中继指令的名称 private bool isFooEnabled; //会在 setter 中添加 FooCommand.NotifyCanExecuteChanged(); public IRelayCommand FooCommand { get; } }

验证属性的值是否有效

如果希望在一个 ObservableValidator 对象中验证属性的值是否有效,可以为字段添加 NotifyDataErrorInfo 特性:

C#
public partial class SignUpViewModel : ObservableValidator { [Required] [EmailAddress] [ObservableProperty] [NotifyDataErrorInfo] private string email = ""; //会在 setter 中添加 ValidateProperty(value, "Email") 的代码

为生成的属性添加特性

如果希望为生成的属性添加额外的特性,尤其比如 JsonIgnore 等,从而在序列化时忽略这个属性,可以使用下面这个特殊语法:

C#
public partial class MainViewModel : ObservableObject { [ObservableProperty] [property: JsonIgnore] private string name = ""; }

希望在属性值发生变化后执行额外的逻辑

如果希望在属性值发生变化后执行额外的逻辑,还可以借助分部方法来实现。从 基本用法 的中给出的后台生成的完整代码中可以发现,setter 中存在一些分部方法,名称为 `OnChanged。借助这些分部方法,我们就可以实现这个需求。形如:

C#
public partial class MainViewModel : ObservableObject { [ObservableProperty] private string name = ""; partial void OnNameChanged(string value) { // Do something } partial void OnNameChanged(string oldValue, string newValue) { // Do something } }

消息中继/事件总线/发布-订阅

Messenger 是一个消息传递机制,它可以让对象之间进行通信,而不需要它们之间有直接的引用关系。从设计模式的角度来说,Messenger 其实是中介者模式的一种实现。

image.png

可以看出,在使用中介者模式之后,个模块之间不再呈现出网状结构,而是变成了星状结构。这样一来,模块之间的耦合就会大大降低,代码也会变得更加简洁。

Messenger 在很多 MVVM 框架中均能找到它的身影。虽然叫法不同,但是背后的原理及逻辑都是相通的。

image.png

本文作者:zhusenlin

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 版权所有:zhusenlin 许可协议。转载请注明出处!