Exemplo n.º 1
0
        /// <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);
                    }
                }
            }
        }