Использование 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));