2010-09-28 158 views
1

我有一個observableCollection並在MyObject中連接了一個事件,是否有一種cunnign方式在集合中捕獲該事件,而無需重新編寫集合類?如何在收集元素對象觸發事件時觸發事件

public class MyObjectCollection : ObservableCollection<MyObject> 
    { 
     public MyObjectCollection() 
     { 
      //some cunning code here 
     } 
    } 

我懷疑必須重新寫入的ObservableCollection類,但不幸的是沒有接口(像有一個IDictionary)在繼承

+0

「沒有界面」:我不明白這個評論,你是什麼意思? – 2010-09-28 22:08:29

回答

2

青睞組合物。而不是擴展ObservableCollection,實現你需要的接口(可能是INotifyCollectionChanged和IList),並保留一個ObservableCollection作爲私有字段。這樣你就可以連接你自己的添加和刪除調用,並根據添加到集合中的對象做你想做的事情。

+0

是的,這就是我的想法。我已經開始沿着這條路走下去,但只是想檢查一下我是否缺少一些'魔術' – 2010-09-28 22:54:33

+0

向我們展示了一些你在這個解決方案中結束的代碼? – 2011-07-29 13:13:44

1

再次讀這篇文章,我覺得你這樣的事情之後是:

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

這是粗糙的和未經考驗的,但它應該給你的基本理念。您可以使用這樣的:

 var collection = new ObservableCollection<Foo>(); 
     var monitor = 
      new CollectionEventMonitor<Foo, EventArgs>(collection, 
       (foo,handler) => foo.Bar += handler, 
       (foo,handler) => foo.Bar -= handler); 

這種方法的好處是,你可以監控項目事件的任何可觀察到的集合,而不是創建一個特殊的包裝集合。您還可以爲同一個集合創建多個監視器實例,允許不同的上下文監視同一個集合上的不同項目事件。

+0

感謝這非常有創意。我想我會選擇A,我認爲選項A的封裝性和可維護性更好。不過,我會將這一個文件歸檔,因爲我認爲它可能適用於更復雜的場景。 – 2010-09-29 00:56:29