You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MAUI中MVVM工具链:只读属性的PropertyChanged通知传递问题

.NET MAUI中Mvvm.CommunityToolkit实现多层依赖只读属性的通知优化

问题背景

在.NET MAUI应用中,使用Mvvm.CommunityToolkit的源生成功能实现INotifyPropertyChanged,现有代码如下:

[ObservableProperty]
[NotifyPropertyChangedFor(nameof(FullName))]
private string? firstName;

[ObservableProperty]
[NotifyPropertyChangedFor(nameof(FullName))]
private string? lastName;

public string FullName => $"{FirstName} {LastName}";

public int NumberOfXsInName => FullName.Count(x => char.ToLower(x) == 'x');

FullName作为只读属性能正常触发UI绑定更新,但依赖FullName的NumberOfXsInName无法自动收到PropertyChanged通知。若给所有触发FullName更新的属性添加[NotifyPropertyChangedFor],不仅缺乏健壮性,也无法强制子类正确实现;手动在构造函数中订阅事件触发通知又过于繁琐。

实际场景中,需基于依赖数据源和过滤函数的只读属性FilteredCollection做分组,要求分组属性随FilteredCollection更新自动触发通知,需更简洁的实现方案。

解决方案

推荐方案:使用[DependsOn]属性定义依赖链

Mvvm.CommunityToolkit提供的[DependsOn]属性可直接标记只读属性的依赖项,源生成器会自动处理PropertyChanged通知的触发,无需手动添加NotifyPropertyChangedFor或订阅事件。

针对姓名示例的改造

[ObservableProperty]
private string? firstName;

[ObservableProperty]
private string? lastName;

// 标记FullName依赖FirstName和LastName
[DependsOn(nameof(FirstName), nameof(LastName))]
public string FullName => $"{FirstName} {LastName}";

// 标记NumberOfXsInName依赖FullName
[DependsOn(nameof(FullName))]
public int NumberOfXsInName => FullName.Count(x => char.ToLower(x) == 'x');

此时,FirstName或LastName变化时,会自动触发FullName的通知;FullName变化时,又会自动触发NumberOfXsInName的通知,完全无需手动干预。

针对分组场景的实现

假设存在DataSource和FilterPredicate两个可观察属性,FilteredCollection依赖二者,分组属性又依赖FilteredCollection,代码如下:

[ObservableProperty]
private ObservableCollection<Item> dataSource;

[ObservableProperty]
private Func<Item, bool> filterPredicate;

[DependsOn(nameof(DataSource), nameof(FilterPredicate))]
public IReadOnlyCollection<Item> FilteredCollection => DataSource.Where(FilterPredicate).ToList();

[DependsOn(nameof(FilteredCollection))]
public IEnumerable<IGrouping<string, Item>> GroupedItems => FilteredCollection.GroupBy(item => item.Category);

DataSource或FilterPredicate变化时,FilteredCollection自动触发通知;FilteredCollection更新后,GroupedItems也会自动触发UI绑定更新。

备选方案:利用生成的Partial方法扩展

若需更灵活的逻辑控制,可借助Mvvm.CommunityToolkit生成的On[PropertyName]Changed partial方法,在属性变化时手动触发下游属性的通知:

[ObservableProperty]
private string? firstName;

[ObservableProperty]
private string? lastName;

public string FullName => $"{FirstName} {LastName}";

public int NumberOfXsInName => FullName.Count(x => char.ToLower(x) == 'x');

partial void OnFirstNameChanged(string? oldValue, string? newValue)
{
    RaisePropertyChanged(nameof(FullName));
    RaisePropertyChanged(nameof(NumberOfXsInName));
}

partial void OnLastNameChanged(string? oldValue, string? newValue)
{
    RaisePropertyChanged(nameof(FullName));
    RaisePropertyChanged(nameof(NumberOfXsInName));
}

此方式适合需要在属性变化时执行额外逻辑的场景,但相比[DependsOn],代码冗余度更高。

总结

[DependsOn]属性是解决多层依赖只读属性通知问题的最优方案,它清晰定义了属性间的依赖关系,自动处理通知触发,大幅提升代码的健壮性和可维护性,尤其适合复杂的依赖链场景。

内容的提问来源于stack exchange,提问作者Hottemax

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 11:37:50