我正在使用ReactiveUI和提供的ReactiveCollection<>
类。
在ViewModel中我有一组对象,我希望创建一个observable来监视这些项目的IsValid属性。
这是我试图解决的问题。在我的ViewModel构造函数中。
this.Items = new ReactiveCollection<object>();
IObservable<bool> someObservable = // ... how do I watch Items so when
// any items IsValid property changes,
// this observable changes. There
// is an IValidItem interface.
this.TheCommand = new ReactiveCommand(someObservable);
...
interface IValidItem { bool IsValid { get; } }
编辑保罗的回答让我大部分都在那里。解决方案如下。
this.Items = new ReactiveCollection<object>();
this.Items.ChangeTrackingEnabled = true;
var someObservable = this.Items.Changed
.Select(_ => this.Items.All(i => i.IsValid));
答案 0 :(得分:5)
这取决于你想要做什么与IsValid的结果。这是我如何做到的,虽然它并不完全直观:
// Create a derived collection which are all the IsValid properties. We don't
// really care which ones are valid, rather that they're *all* valid
var isValidList = allOfTheItems.CreateDerivedCollection(x => x.IsValid);
// Whenever the collection changes in any way, check the array to see if all of
// the items are valid. We could probably do this more efficiently but it gets
// Tricky™
IObservable<bool> areAllItemsValid = isValidList.Changed.Select(_ => isValidList.All());
theCommand = new ReactiveCommand(areAllItemsValid);
答案 1 :(得分:1)
由于您使用的是ReactiveUI,因此您有几个选择。如果您的对象是ReactiveValidatedObject
s,您实际上可以使用ValidationObservable:
var someObservable = this.Items
.Select(o => o.ValidationObservable
.Select(chg => chg.GetValue()) //grab just the current bool from the change
.StartsWith(o.IsValid)) //prime all observables with current value
.CombineLatest(values => values.All());
如果它们不是ReactiveValidatedObjects,而是实现INotifyPropertyChanged,则只需替换第一行,并在ReactiveUI中为这些对象使用方便的ObservableForProperty扩展方法。您可以使用o.ValidationObservable
代替o.ObservableForProperty(x => x.IsValid)
。其余的应该是一样的。
这是一个非常常见的用例,我将其包装在IEnumerable<ReactiveValidatedObject>
我确信Paul Betts会有更优雅的东西,但这就是我所做的。