Reputation: 1187
I have an observableCollection and have wired up an event in MyObject, is there an cunnign way to grab that event in the collection without having to re-write the collection class?
public class MyObjectCollection : ObservableCollection<MyObject>
{
public MyObjectCollection()
{
//some cunning code here
}
}
I suspect I have to re-write the ObservableCollection Class, but unfortunatly there is no interface (like there is an IDictionary)
Upvotes: 1
Views: 168
Reputation: 27505
Reading this again, I think you're after something like this:
public sealed class CollectionEventMonitor<TItem, TEventArgs> : IDisposable
where TEventArgs: EventArgs
{
private readonly INotifyCollectionChanged _collection;
private readonly Action<TItem, EventHandler<TEventArgs>> _addEvent;
private readonly Action<TItem, EventHandler<TEventArgs>> _removeEvent;
public event EventHandler<TEventArgs> ItemFiredEvent;
public CollectionEventMonitor(INotifyCollectionChanged collection,
Action<TItem, EventHandler<TEventArgs>> addEvent,
Action<TItem, EventHandler<TEventArgs>> removeEvent)
{
_addEvent = addEvent;
_removeEvent = removeEvent;
_collection = collection;
_collection.CollectionChanged += _collection_CollectionChanged;
}
void _collection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (var item in e.NewItems.Cast<TItem>())
_addEvent(item, OnItemFiredEvent);
break;
case NotifyCollectionChangedAction.Remove:
foreach (var item in e.OldItems.Cast<TItem>())
_removeEvent(item, OnItemFiredEvent);
break;
case NotifyCollectionChangedAction.Replace:
foreach (var item in e.OldItems.Cast<TItem>())
_removeEvent(item, OnItemFiredEvent);
foreach (var item in e.NewItems.Cast<TItem>())
_addEvent(item, OnItemFiredEvent);
break;
case NotifyCollectionChangedAction.Move:
break;
case NotifyCollectionChangedAction.Reset:
foreach (var item in e.OldItems.Cast<TItem>())
_removeEvent(item, OnItemFiredEvent);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
private void OnItemFiredEvent(Object item, TEventArgs eventArgs)
{
var handler = ItemFiredEvent;
if (handler != null)
handler(item, eventArgs);
}
public void Dispose()
{
_collection.CollectionChanged -= _collection_CollectionChanged;
}
}
This is rough and untested, but it should give you the basic idea. You use it like this:
var collection = new ObservableCollection<Foo>();
var monitor =
new CollectionEventMonitor<Foo, EventArgs>(collection,
(foo,handler) => foo.Bar += handler,
(foo,handler) => foo.Bar -= handler);
The advantage of this approach is that you can monitor any observable collection for item events, rather than creating a special wrapper collection. You can also create multiple instances of the monitor for the same collection, allowing different contexts to monitor different events of items on the same collection.
Upvotes: 1
Reputation: 487
Favor composition over inheritance. Instead of extending ObservableCollection, implement the interfaces you need (probably INotifyCollectionChanged and IList) and keep an ObservableCollection as a private field. That way you can wire your own add and remove calls and do what you want with the objects added to the collection.
Upvotes: 2