【问题标题】:How to observe a collection of items for when they are all valid?如何观察一组项目何时都有效?
【发布时间】:2012-06-27 06:55:26
【问题描述】:

我正在使用 ReactiveUI 和提供的 ReactiveCollection<> 类。

在 ViewModel 中,我有一个对象集合,我希望创建一个可观察对象来监视这些项目的 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));

【问题讨论】:

  • 在使用Changed observable 时有没有办法避免离开monad?我自己的代码中也有类似的东西,但是不得不忽略序列中的值并退出以获得完整的属性值(this.Items 这里)感觉有点笨拙。 ://
  • @MalRoss 不确定更改后的 observable 会给您带来什么。如果它在更改时为您提供集合的快照,则可以留在 monad 中,但我怀疑 ReactiveCollection 很懒惰,最多只是返回更改的对象。

标签: system.reactive reactiveui


【解决方案1】:

这取决于你想用 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);

【讨论】:

  • 那么 isValidList 是干什么用的?第二部分应该是 isValidList.Changed.Selected(... 而不是 allOfTheItems?
  • hwhoops,通过文本区域编码。固定!
【解决方案2】:

由于您使用的是 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.ObservableForProperty(x =&gt; x.IsValid) 而不是o.ValidationObservable。其余的应该是一样的。

这是一个非常常见的用例,我已将其包装在 IEnumerable&lt;ReactiveValidatedObject&gt; 的扩展方法中

我确信 Paul Betts 会带来更优雅的东西,但这就是我所做的。

【讨论】:

    猜你喜欢
    • 2020-08-17
    • 1970-01-01
    • 2019-09-26
    • 2021-06-26
    • 2012-11-09
    • 1970-01-01
    • 2018-06-20
    • 2012-05-11
    • 2021-07-04
    相关资源
    最近更新 更多