using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Linq; using Developpez.Dotnet.Windows.Properties; namespace Developpez.Dotnet.Windows.Collections { /// /// Représente une collection d'objet qui fournit des notifications quand des éléments sont ajoutés ou /// supprimés, ou quand la collection entière est modifiée. Fournit une méthode permettant d'ajouter /// plusieurs objets à la fois en ne déclenchant qu'une seule notification par groupe d'éléments supprimés. /// /// Type des éléments de la collection public class RangeObservableCollection : ObservableCollection { /// /// Initialise une nouvelle instance vide de RangeObservableCollection<T> /// public RangeObservableCollection() { } /// /// Initialise une nouvelle instance de RangeObservableCollection<T> en y copiant /// les éléments de la séquence spécifiée. /// /// La séquence à partir de laquelle copier les éléments public RangeObservableCollection(IEnumerable source) : base(source) { } /// /// Ajoute tous les éléments spécifiés à la collection. Cette méthode ne déclenche qu'une seule notification pour tous les éléments ajoutés, /// et non une notification par élément ajouté. /// /// Les éléments à ajouter public void AddRange(IEnumerable items) { items.CheckArgumentNull("items"); var addedItems = new List(); int startingIndex = this.Count; foreach (var item in items) { this.Items.Add(item); addedItems.Add(item); } var args = new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Add, addedItems, startingIndex); OnCollectionChanged(args); } /// /// Insère tous les éléments spécifiés à l'index spécifié de la collection. Cette méthode ne déclenche qu'une seule notification pour tous les éléments insérés, /// et non une notification par élément inséré. /// /// L'index auquel insérer les éléments /// Les éléments à insérer public void InsertRange(int index, IEnumerable items) { index.CheckArgumentOutOfRange("index", 0, this.Count, ExceptionMessages.ArgMustBeInRange); items.CheckArgumentNull("items"); var addedItems = new List(); int startingIndex = index; foreach (var item in items) { this.Items.Insert(index++, item); addedItems.Add(item); } var args = new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Add, addedItems, startingIndex); OnCollectionChanged(args); } /// /// Supprime le nombre d'éléments spécifié à partir de l'index spécifié de la collection. Cette méthode ne déclenche qu'une seule notification pour tous les éléments supprimés, /// et non une notification par élément supprimé. /// /// L'index à partir duquel supprimer les éléments /// Le nombre d'éléments à supprimer public void RemoveRange(int index, int count) { index.CheckArgumentOutOfRange("index", 0, int.MaxValue, ExceptionMessages.ArgMustBePositive); count.CheckArgumentOutOfRange("count", 0, int.MaxValue, ExceptionMessages.ArgMustBePositive); if (index + count > this.Count) throw new ArgumentException(ExceptionMessages.RemoveRangeBadArgs); var removedItems = new List(); int startingIndex = index; for (int i = 0; i < count; i++) { removedItems.Add(this.Items[index]); this.Items.RemoveAt(index); } var args = new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Remove, removedItems, startingIndex); OnCollectionChanged(args); } /// /// Supprime tous les éléments de la collection qui vérifient la condition spécifiée. /// Cette méthode déclenche une notification par groupe d'éléments contigus supprimés, /// et non une notification par élément supprimé. /// /// La condition à vérifier public void RemoveAll(Predicate predicate) { predicate.CheckArgumentNull("predicate"); int index = 0; int startIndex = 0; int count = 0; while (index < this.Count) { if (predicate(this.Items[index])) { count++; index++; } else { if (count > 0) { this.RemoveRange(startIndex, count); } startIndex++; index = startIndex; count = 0; } } if (count > 0) { this.RemoveRange(startIndex, count); } } /// /// Remplace les éléments de la collection par les éléments spécifiés à partir /// de la position spécifiée. Cette méthode ne déclenche qu'une seule notification /// pour tous les éléments remplacés, et non une notification par élément remplacé. /// /// Position à partir de laquelle remplacer les éléments /// Eléments avec lesquels remplacer les valeurs existantes public void ReplaceRange(int startIndex, IEnumerable newItems) { startIndex.CheckArgumentOutOfRange("startIndex", 0, this.Count - 1, ""); newItems.CheckArgumentNull("newItems"); var newItems2 = newItems.ToList(); if (startIndex + newItems2.Count > this.Count) throw new ArgumentException(ExceptionMessages.ReplaceRangeBadArgs); var oldItems = new List(); int index = startIndex; foreach (var item in newItems2) { oldItems.Add(this.Items[index]); this.Items[index] = item; index++; } var args = new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Replace, newItems2, oldItems, startIndex); OnCollectionChanged(args); } } }