Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

observer on a collection

I am taking my first steps in Rx frameworks on .net 4. i am trying to observe a collection like List<int> or Dictionary<x,x>. and when a item is added to the collection it will write it ToString() in the console.

any ideas ? or some code samples thanks

like image 438
guyl Avatar asked Jan 18 '11 08:01

guyl


2 Answers

List<T> and Dictionary<TKey, TValue> are not observable (they do not raise events when they change), so there is nothing for Rx to hook into.

For List, you can use ObservableCollection<T>, but you would need to wrap its events to use it from Rx. Here is an example using extension methods:

public static class ObservableCollectionExtensions
{
    public static IObservable<IEvent<NotifyCollectionChangedEventArgs>> 
        GetObservableChanges<T>(this ObservableCollection<T> collection)
    {
        return Observable.FromEvent<
            NotifyCollectionChangedEventHandler, NotifyCollectionChangedArgs>(
                h => new NotifyCollectionChangedEventHandler(h),
                h => collection.CollectionChanged += h,
                h => collection.CollectionChanged -= h
            );
    }

    public static IObservable<T> GetObservableAddedValues<T>(
        this ObservableCollection<T> collection)
    {
        return collection.GetObservableChanges()
            .Where(evnt => evnt.EventArgs.Action == NotifyCollectionChangedAction.Add)
            .SelectMany(evnt => evnt.EventArgs.NewItems.Cast<T>());
    }
}

I've included an additional helper that only exposes the newly added items as an IObservable<T>, which you can use like this:

ObservableCollection<int> collection = 
    new ObservableCollection<int>(new int[] { 1, 2, 3 });

collection.GetObservableAddedValues().Subscribe(
    i => Console.WriteLine("{0} was added", i)
);

There is no observable Dictionary in the framework, though the ObservableDictionary codeplex project appears to fill that gap and I'm sure it could be wrapped in a similar way.

like image 141
Richard Szalay Avatar answered Sep 23 '22 20:09

Richard Szalay


Use ReactiveCollection from ReactiveUI:

var c = new ReactiveCollection<int>();
c.Changed.Subscribe(x => Console.Writeln(x.Value);
c.Add(1);
like image 33
Lukas Cenovsky Avatar answered Sep 22 '22 20:09

Lukas Cenovsky