2

I'm using ReactiveUI and the provided ReactiveCollection<> class.

In a ViewModel I have a collection of objects, and I wish to create an observable that watches those items for their IsValid property.

This is the scenario I'm trying to solve. In my ViewModel's constructor.

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; } }

EDIT Ana's answer got me most of the way there. The solution is the following.

this.Items = new ReactiveCollection<object>();
this.Items.ChangeTrackingEnabled = true;

var someObservable = this.Items.Changed
    .Select(_ => this.Items.All(i => i.IsValid));
4

2 回答 2

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);
于 2012-06-27T17:59:44.933 回答
1

由于您使用的是 ReactiveUI,因此您有几个选择。如果您的对象是ReactiveValidatedObjects,您实际上可以使用 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 会带来更优雅的东西,但这就是我所做的。

于 2012-06-27T14:44:01.640 回答