Использование Rx (Reactive Extensions) для просмотра определенного элемента в ObservableCollection

У меня есть 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 не может содержать никаких элементов для начала, а значения свойств поступают несинхронно. Я знаю, что последняя строка неверна, мне нужно иметь Observable в классе PropertyChanged в пределах лямбда... но я все еще запутался в том, как просто получить эту оценку, когда выполняются оба условия.

Ответ 1

Добавьте ReactiveUI в свой проект, тогда вы можете использовать класс ReactiveCollection, который происходит из WPF ObservableCollection. Тогда это легко, как пирог:

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

Ответ 2

Общий ObservableCollection не имеет ничего общего с интерфейсом IObservable. Тем не менее вы можете отслеживать событие ObservableCollection CollectionChanged через Rx, используя следующее:

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

Это даст вам уведомление, когда элементы (элементы) добавляются в ObservableCollection. Элементы будут non-generic IList, поэтому мы можем отнести это к IEnumerable из базового SomeType и SelectMany на этом .AsObservable, чтобы получить новый наблюдаемый поток входящих значений. Наконец, в подписке вы делаете то, что хотите, с конечным значением (вместо использования первого вызова блокировки):

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