【问题标题】:Using Rx (Reactive Extensions) to watch for specific item in ObservableCollection使用 Rx (Reactive Extensions) 监视 ObservableCollection 中的特定项目
【发布时间】:2011-08-31 17:08:24
【问题描述】:

我有一个 ObservableCollection,我需要为特定项目引用它。如果该项目不存在,我需要通过 Reactive Extensions 监视它是否/何时出现项目,但在设置语句时需要一些帮助。我仍然不熟悉所有不同的 Linq 扩展是如何工作的,所以我不确定如何做到这一点。谁能指出我正确的方向?

为了更好地说明,我需要如下所示:

public class myitem :INotifyPropertyChanged
{
    private string _key;
    private string _value;

    public string key
    {
        get { return _key; }
        set { _key = value; NotifyPropertyChanged("key"); }
    }

    public string myvalue
    {
        //proper getter/setter, blah, blah
    }
}

ObservableCollection<myitem> _collection = mycollection;
var x = Observable.FromEvent<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
    h => new NotifyCollectionChangedEventHandler(h),
    h => _collection.CollectionChanged += h,
    h => _collection.CollectionChanged -= h);

string keywaitingfor = "thiskey";
string valuewaitingfor = x.Where(xx => xx.key == keywaitingfor).First().myvalue;

这不完全是我的场景,但希望你能看到我想要做什么。 ObservableCollection 可能不包含要开始的项目,并且属性值异步传入。我知道最后一行是不正确的,我需要在 lambda 中的类 PropertyChanged 事件上有一个 Observable ......但我仍然对如何在满足两个条件时等待该值感到困惑。

【问题讨论】:

    标签: c# linq observablecollection system.reactive


    【解决方案1】:

    通用 ObservableCollection 与 IObservable 接口无关。但是,您可以使用以下命令通过 Rx 监控 ObservableCollection 的 CollectionChanged 事件:

    ObservableCollection<SomeType> items = yourObserableCollection;
    var itemAddedObservable = Observable
             .FromEventPattern<NotifyCollectionChangedEventArgs>(items, "CollectionChanged")
             .Select(change => change.EventArgs.NewItems)
    

    每当项目被添加到 ObservableCollection 时,这都会给你一个通知。这些项目将是一个非泛型 IList,因此我们可以将其转换为底层 SomeType 的 IEnumerable 和该 .AsObservable 上的 SelectMany 以获得传入值的新可观察流。最后在订阅中,你可以用最终值做你想做的事(而不是使用阻塞的 First 调用):

    var filteredAddedItem = from added in itemAddedObservable
                            from itemAdded in added.OfType<SomeType>().ToObservable()
                            where itemAdded.key = keywaitingfor
                            select itemAdded;
    
    var sub = filteredAddedItem.Subscribe(item => Console.WriteLine("Received " + item.myvalue));
    

    【讨论】:

    • +1。一个问题 - 我有这个 keywaitingfor 存在于另一个集合中。如何搜索或匹配该其他集合中的 itemAdded.Key
    【解决方案2】:

    将 ReactiveUI 添加到您的项目中,然后您可以使用派生自 WPF 的 ObservableCollection 的 ReactiveCollection 类。那么这很容易:

    theCollection.ItemsAdded
        .Where(x => x.Key == "Foo")
        .Subscribe(x => Console.WriteLine("Received Item!"));
    

    【讨论】:

    • ObservableCollection 现在是一种不幸的命名选择 :( 这是进行 Rx 训练时遇到的问题。
    • 看起来正是我所需要的。
    • 我没有意识到 ReactiveUI 会成为一个如此广泛的库。看起来不错;我只是希望我几个月前就知道它,目前它可能不适合我的项目。因此,虽然我希望将来可以使用它,并且它是“一个”答案,但我需要取消选择它作为“已接受”的答案。
    • 您可以做的另一件事是将github.com/xpaulbettsx/ReactiveUI/blob/master/ReactiveUI/… 复制粘贴到您的项目中,并将所有 RxApp.DeferredScheduler 更改为 DispatcherScheduler.Current
    • @JonathanPeel ReactiveCollection 已弃用 - 该库现在使用 Roland Pheasant 的 DynamicData - dynamic-data.org - 功能更强大。
    猜你喜欢
    • 2011-05-03
    • 1970-01-01
    • 2012-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多