#region CPL License /* Nuclex Framework Copyright (C) 2002-2013 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; #if !NO_SPECIALIZED_COLLECTIONS using System.Collections.Specialized; #endif namespace Nuclex.Support.Collections { /// Collection which fires events when items are added or removed /// Type of items the collection manages public class ObservableCollection : ICollection, ICollection, #if !NO_SPECIALIZED_COLLECTIONS INotifyCollectionChanged, #endif IObservableCollection { /// Raised when an item has been added to the collection public event EventHandler> ItemAdded; /// Raised when an item is removed from the collection public event EventHandler> ItemRemoved; /// Raised when an item is replaced in the collection public event EventHandler> ItemReplaced { add { } remove { } } /// Raised when the collection is about to be cleared /// /// This could be covered by calling ItemRemoved for each item currently /// contained in the collection, but it is often simpler and more efficient /// to process the clearing of the entire collection as a special operation. /// public event EventHandler Clearing; /// Raised when the collection has been cleared public event EventHandler Cleared; #if !NO_SPECIALIZED_COLLECTIONS /// Called when the collection has changed public event NotifyCollectionChangedEventHandler CollectionChanged; #endif /// Initializes a new ObservableCollection with no items public ObservableCollection() : this(new Collection()) { } /// /// Initializes a new ObservableCollection as a wrapper for an existing collection /// /// Collection that will be wrapped /// List is null public ObservableCollection(ICollection collection) { this.typedCollection = collection; this.objectCollection = (collection as ICollection); } /// Removes all elements from the Collection public void Clear() { OnClearing(); this.typedCollection.Clear(); OnCleared(); } /// Adds an item to the collection /// Collection an item will be added to public void Add(TItem item) { this.typedCollection.Add(item); OnAdded(item); } /// Determines whether the collection contains the specified item /// Item the collection will be searched for /// /// True if the collection contains the specified item, false otherwise /// public bool Contains(TItem item) { return this.typedCollection.Contains(item); } /// Copies the contents of the collection into an array /// Array the collection's contents will be copied into /// /// Index in the array where the collection's first item will be placed /// public void CopyTo(TItem[] array, int arrayIndex) { this.typedCollection.CopyTo(array, arrayIndex); } /// The total number of items currently in the collection public int Count { get { return this.typedCollection.Count; } } /// Whether the collection is read-only public bool IsReadOnly { get { return this.typedCollection.IsReadOnly; } } /// Removes an item from the collection /// Item that will be removed from the collection /// True if the item was found and removed, false otherwise public bool Remove(TItem item) { bool wasRemoved = this.typedCollection.Remove(item); if(wasRemoved) { OnRemoved(item); } return wasRemoved; } /// Returns an enumerator for the items in the collection /// An enumeration for the items in the collection public IEnumerator GetEnumerator() { return this.typedCollection.GetEnumerator(); } /// Fires the 'ItemAdded' event /// Item that has been added to the collection protected virtual void OnAdded(TItem item) { if(ItemAdded != null) { ItemAdded(this, new ItemEventArgs(item)); } #if !NO_SPECIALIZED_COLLECTIONS if(CollectionChanged != null) { CollectionChanged( this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item) ); } #endif } /// Fires the 'ItemRemoved' event /// Item that has been removed from the collection protected virtual void OnRemoved(TItem item) { if(ItemRemoved != null) { ItemRemoved(this, new ItemEventArgs(item)); } #if !NO_SPECIALIZED_COLLECTIONS if(CollectionChanged != null) { CollectionChanged( this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item) ); } #endif } /// Fires the 'Clearing' event protected virtual void OnClearing() { if(Clearing != null) { Clearing(this, EventArgs.Empty); } } /// Fires the 'Cleared' event protected virtual void OnCleared() { if(Cleared != null) { Cleared(this, EventArgs.Empty); } #if !NO_SPECIALIZED_COLLECTIONS if(CollectionChanged != null) { CollectionChanged(this, Constants.NotifyCollectionResetEventArgs); } #endif } #region IEnumerable implementation /// Returns an enumerator for the items in the collection /// An enumeration for the items in the collection IEnumerator IEnumerable.GetEnumerator() { return this.objectCollection.GetEnumerator(); } #endregion // IEnumerable implementation #region ICollection implementation /// Copies the contents of the collection into an array /// Array the collection's contents will be copied into /// /// Index in the array where the collection's first item will be placed /// void ICollection.CopyTo(Array array, int arrayIndex) { this.objectCollection.CopyTo(array, arrayIndex); } /// Whether the collection synchronizes accesses from multiple threads bool ICollection.IsSynchronized { get { return this.objectCollection.IsSynchronized; } } /// /// Synchronization root used to synchronize threads accessing the collection /// object ICollection.SyncRoot { get { return this.objectCollection.SyncRoot; } } #endregion // IEnumerable implementation /// The wrapped collection under its type-safe interface private ICollection typedCollection; /// The wrapped collection under its object interface private ICollection objectCollection; } } // namespace Nuclex.Support.Collections