如何借助INotifyPropertyChanged实现属性间的绑定桥接?
MVVM架构下View与DomainModel解耦的优雅属性桥接方案
背景
我开发了一个采用MVVM架构的应用,其中一组DomainModel类均实现了INotifyPropertyChanged接口,数据会根据内部逻辑自动更新。程序通过绑定ViewModel在View上展示部分数据,我希望将View与DomainModel的实现细节彻底解耦,同时符合迪米特法则。
当前绑定与期望目标
当前绑定代码
<StatusBarItem Visibility="{Binding Status.Connected, Converter={StaticResource BoolToVisibilityConverter}}"> <TextBlock Text="{Binding SystemTime.Time, StringFormat='HH:mm:ss dd.MM.yyyy'}"/> </StatusBarItem>
期望的绑定代码
<StatusBarItem Visibility="{Binding Connected, Converter={StaticResource BoolToVisibilityConverter}}"> <TextBlock Text="{Binding SystemTime, StringFormat='HH:mm:ss dd.MM.yyyy'}"/> </StatusBarItem>
现有尝试与疑问
我了解CommunityToolkit.Mvvm中有如下特性:
[NotifyPropertyChangedFor(nameof(FullName))] private string? name;
它会在Name属性变化时自动触发FullName的变更通知,但我需要的是反向逻辑——当DomainModel中的Time属性变化时,通知ViewModel中对应的SystemTime属性更新。
我坚持一个原则:DomainModel绝对不能知晓ViewModel的任何信息,这属于不良架构设计,模型层不应依赖视图相关的内容。
我尝试过手动订阅变更事件的方案:
public class StatusBarViewModel : ObservableObject { private readonly DomainDataService _dataService; private readonly ConnectionStatusService _statusService; public long Speed => _statusService.Speed; public bool Connected => _statusService.Connected; public DateTime SystemTime => _dataService.SystemTime.Time; public StatusBarViewModel(DomainDataService dataService, ConnectionStatusService statusService) { _dataService = dataService; _statusService = statusService; _statusService.PropertyChanged += (_, args) => { switch (args.PropertyName) { case nameof(_statusService.Speed): OnPropertyChanged(nameof(Speed)); break; case nameof(_statusService.Connected): OnPropertyChanged(nameof(Connected)); break; } }; _dataService.SystemTime.PropertyChanged += (_, args) => { if(args.PropertyName == nameof(_dataService.SystemTime.Time)) OnPropertyChanged(nameof(SystemTime)); }; } }
但这个方案过于繁琐,当属性数量增多时,代码会变得臃肿,而且我担心大量的事件订阅会影响性能。有没有更优雅的属性桥接方式?
更新1:当前ViewModel实现
public class StatusBarViewModel : ObservableObject { public SystemTime SystemTime { get; } public ConnectionStatusService Status { get; } public StatusBarViewModel(DomainDataService dataService, ConnectionStatusService statusService) { SystemTime = dataService.SystemTime; Status = statusService; } }
内容的提问来源于stack exchange,提问作者Ж. Сергей
相关产品推荐
相关产品推荐

