using System; using System.Collections.Generic; using System.Linq; using System.Collections; using System.Collections.Specialized; using Chernobyl.Event; namespace Chernobyl.Collections.Generic.Event { /// /// Converts the events raised by to the /// event raised by /// public class NotifyCollectionChanged : INotifyCollectionChanged, IEnumerable { /// /// Initializes a new instance of the /// class. /// /// The instance whose raised events are being /// converted to the raised /// event. /// Null is a permitted value for this parameter if /// will be set later. public NotifyCollectionChanged(IEventEnumerable enumerable) { // Null check not performed because null values are permitted. Enumerable = enumerable; } /// /// An event that is raised when changes. /// public event NotifyCollectionChangedEventHandler CollectionChanged; /// /// The instance whose raised events are being converted to the raised /// event. If /// null is set on this instance than this will stop listening to the /// previously observed . /// public IEventEnumerable Enumerable { get { return _enumerable; } set { if (_enumerable != value) { _enumerableCopy = null; // Stop listening to the old enumerable. if (_enumerable != null) { _enumerable.ItemsAdded -= OnItemsAdded; _enumerable.ItemsRemoved -= OnItemsRemoved; } // Start listening to the new enumerable _enumerable = value; if (_enumerable != null) { UpdateCopy(); _enumerable.ItemsAdded += OnItemsAdded; _enumerable.ItemsRemoved += OnItemsRemoved; } } } } /// /// Returns an enumerator that iterates through a collection. /// /// /// An object that can be used to iterate /// through the collection. /// public IEnumerator GetEnumerator() { if (Enumerable == null) throw new NullReferenceException("Failed to get the IEnumerator. " + "NotifyCollectionChanged.Enumerable " + "must be set to get the IEnumerator. " + "It is currently null."); return Enumerable.GetEnumerator(); } /// /// Raises the /// if applicable. /// /// The sender of the event. /// The instance containing /// the event data. void OnItemsAdded(object sender, ItemsEventArgs e) { if (CollectionChanged != null) { int index = Enumerable.Cast() .TakeWhile(item => item != e.Items.First()).Count(); UpdateCopy(); CollectionChanged(this, new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Add, new ArrayList(e.Items), index)); } } /// /// Raises the /// if applicable. /// /// The sender of the event. /// The instance containing /// the event data. void OnItemsRemoved(object sender, ItemsEventArgs e) { if (CollectionChanged != null) { // Grab the index where the item is removed. int index = _enumerableCopy.TakeWhile(item => item != e.Items.First()).Count(); UpdateCopy(); CollectionChanged(this, new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Remove, new ArrayList(e.Items), index)); } } /// /// Updates . /// void UpdateCopy() { _enumerableCopy = _enumerable.Cast().ToArray(); } /// /// The copy of . This instance is used to /// determine the index of any items removed from . /// Object[] _enumerableCopy; /// /// The backing field to . /// IEventEnumerable _enumerable; } }