Использование Rx (Reactive Extensions) для поиска определенного элемента в ObservableCollection - PullRequest
11 голосов
/ 31 августа 2011

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

Ответы [ 2 ]

14 голосов
/ 31 августа 2011

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

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

Это даст вам уведомление всякий раз, когда элементы добавляются в ObservableCollection. Элементы будут не универсальными 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));
8 голосов
/ 01 сентября 2011

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

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