public static void Move <T>(this ThreadSafeBindingList <T> lstCollection, int intOldIndex, int intNewIndex)
 {
     using (lstCollection.LockObject.EnterWriteLock())
     {
         bool blnOldRaiseListChangedEvents = lstCollection.RaiseListChangedEvents;
         try
         {
             lstCollection.RaiseListChangedEvents = false;
             int intParity = intOldIndex < intNewIndex ? 1 : -1;
             for (int i = intOldIndex; i != intNewIndex; i += intParity)
             {
                 (lstCollection[intOldIndex + intParity], lstCollection[intOldIndex]) = (
                     lstCollection[intOldIndex], lstCollection[intOldIndex + intParity]);
             }
         }
         finally
         {
             lstCollection.RaiseListChangedEvents = blnOldRaiseListChangedEvents;
         }
     }
 }
        /// <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="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 ThreadSafeBindingList <T> lstCollection, IComparer <T> objComparer = null) where T : IComparable
        {
            if (lstCollection == null)
            {
                throw new ArgumentNullException(nameof(lstCollection));
            }
            using (EnterReadLock.Enter(lstCollection.LockObject))
            {
                T[] aobjSorted = new T[lstCollection.Count];
                for (int i = 0; i < lstCollection.Count; ++i)
                {
                    aobjSorted[i] = lstCollection[i];
                }
                Array.Sort(aobjSorted, objComparer);
                bool blnOldRaiseListChangedEvents = lstCollection.RaiseListChangedEvents;
                // Not BitArray because read/write performance is much more important here than memory footprint
                bool[] ablnItemChanged = blnOldRaiseListChangedEvents ? new bool[aobjSorted.Length] : null;
                using (lstCollection.LockObject.EnterWriteLock())
                {
                    // 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)
                    {
                        T   objLoop     = aobjSorted[i];
                        int intOldIndex = lstCollection.IndexOf(objLoop);
                        int intNewIndex = i;
                        if (intOldIndex == intNewIndex)
                        {
                            continue;
                        }
                        if (intOldIndex > intNewIndex)
                        {
                            // Account for removal happening before removal
                            --intOldIndex;
                            if (blnOldRaiseListChangedEvents)
                            {
                                for (int j = intNewIndex; j <= intOldIndex; ++j)
                                {
                                    ablnItemChanged[j] = true;
                                }
                            }
                        }
                        else
                        {
                            // Account for removal happening before removal
                            --intNewIndex;
                            if (blnOldRaiseListChangedEvents)
                            {
                                for (int j = intOldIndex; j <= intNewIndex; ++j)
                                {
                                    ablnItemChanged[j] = true;
                                }
                            }
                        }

                        lstCollection.RemoveAt(intOldIndex);
                        lstCollection.Insert(intNewIndex, objLoop);
                    }

                    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
                    int intResetThreshold = ablnItemChanged.Length / 2;
                    int intCountTrues     = 0;
                    // ReSharper disable once ForCanBeConvertedToForeach
                    for (int i = 0; i < ablnItemChanged.Length; ++i)
                    {
                        if (ablnItemChanged[i])
                        {
                            ++intCountTrues;
                            if (intCountTrues >= intResetThreshold)
                            {
                                lstCollection.ResetBindings();
                                return;
                            }
                        }
                    }

                    for (int i = 0; i < ablnItemChanged.Length; ++i)
                    {
                        if (ablnItemChanged[i])
                        {
                            lstCollection.ResetItem(i);
                        }
                    }
                }
            }
        }