首页 > 解决方案 > 使用 WhenAnyObservable 组合和过滤多个事件

问题描述

我有一个 ViewModel:

当 MyObject 列表或单个 MyObject 中的“Active”属性都不为真时,或者在任何情况下 IsBusy 为真时,我想禁用该命令。

在将 IsBusy 添加到图片之前,我想出的最佳解决方案是:

var canSave = this.WhenAnyObservable(
    x => x.MyObjectsList.ItemChanged, x => x.MyObject.Changed)
    .Where(x => x.PropertyName == "Active")
    .Select(_ => MyObjectsList.Any(x => x.Active) || MyObject.Active);

SaveCommand = ReactiveCommand.Create(Save, canSave);

这个想法是每次 Active 属性更改时都会重新评估。不确定这是否是最好的解决方案(因此欢迎任何改进它的建议),但我绝对无法将 IsBusy 添加到图片中,以便在 IsBusy 时重新评估 Select 子句(包括 IsBusy 状态)变化。

标签: c#.netsystem.reactivereactiveui

解决方案


我认为您的答案可以简化。

var itemChangedObs = this.WhenAnyValue(x => x.MyObject.Active);
var isBusyObs = this.WhenAnyValue(x => x.IsBusy);
var listItemChangedObs = this.WhenAnyObservable(x => x.MyObectsList.ItemChanged).Where(x => x.PropertyName == "Active").Select(_ => MyObjectsList.Any(x => x.Active)).StartsWith(false)
var canRunCommand = itemChangedObs.CombineLatest(listItemChangedObs, isBusyObs, (itemActive, listItemActive, isBusy) => (itemActive || listItemActive) && !isBusy);

这个版本本质上使用了一个 CombineLatest,它在将两个 observables 组合在一起后接受你想要的值的 Lambda。

CombineLatest() 在两个 Observable 都发出值之前不会产生值,因此 listItemChanged 在前面有一个 StartsWith(false) 。

默认情况下,WhenAnyValue() 将始终发出该值的 default(T) 作为其初始值,因此您不需要带有这些语句的 StartsWith。


推荐阅读