/// <summary> /// Sorts the elements in a range of elements in an ObservableCollection using the specified /// System.Collections.Generic.IComparer`1 generic interface. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="lstCollection">The ObservableCollection to sort.</param> /// <param name="index">The starting index of the range to sort.</param> /// <param name="length">The number of elements in the range to sort.</param> /// <param name="objComparer">The System.Collections.Generic.IComparer`1 generic interface /// implementation to use when comparing elements, or null to use the System.IComparable`1 generic /// interface implementation of each element.</param> public static void Sort <T>(this BindingList <T> lstCollection, int index, int length, IComparer <T> objComparer = null) where T : IComparable { if (lstCollection == null) { throw new ArgumentNullException(nameof(lstCollection)); } if (index < 0) { throw new ArgumentOutOfRangeException(nameof(index)); } if (length < 0) { throw new ArgumentOutOfRangeException(nameof(length)); } if (index + length > lstCollection.Count) { throw new ArgumentException(nameof(length)); } if (length == 0) { return; } T[] aobjSorted = new T[length]; for (int i = 0; i < length; ++i) { aobjSorted[i] = lstCollection[index + i]; } Array.Sort(aobjSorted, objComparer); bool blnOldRaiseListChangedEvents = lstCollection.RaiseListChangedEvents; BitArray ablnItemChanged = blnOldRaiseListChangedEvents ? new BitArray(aobjSorted.Length) : null; // We're going to disable events while we work with the list, then call them all at once at the end lstCollection.RaiseListChangedEvents = false; for (int i = 0; i < aobjSorted.Length; ++i) { int intOldIndex = lstCollection.IndexOf(aobjSorted[i]); int intNewIndex = index + i; if (intOldIndex == intNewIndex) { continue; } if (intOldIndex > intNewIndex) { // Account for removal happening before removal intOldIndex -= 1; if (blnOldRaiseListChangedEvents) { for (int j = intNewIndex; j <= intOldIndex; ++j) { ablnItemChanged[j] = true; } } } else { // Account for removal happening before removal intNewIndex -= 1; if (blnOldRaiseListChangedEvents) { for (int j = intOldIndex; j <= intNewIndex; ++j) { ablnItemChanged[j] = true; } } } lstCollection.RemoveAt(intOldIndex); lstCollection.Insert(intNewIndex, aobjSorted[i]); } lstCollection.RaiseListChangedEvents = blnOldRaiseListChangedEvents; if (!blnOldRaiseListChangedEvents) { return; } // If at least half of the list was changed, call a reset event instead of a large amount of ItemChanged events if (ablnItemChanged.CountTrues() >= ablnItemChanged.Length / 2) { lstCollection.ResetBindings(); } else { for (int i = 0; i < ablnItemChanged.Length; ++i) { if (ablnItemChanged[i]) { lstCollection.ResetItem(i); } } } }