protected virtual void OnSorting(SortProgressEventArgs e)
 {
     if (this.Sorting != null)
     {
         this.Sorting.Invoke(this, e);
     }
 }
        /// <summary>
        /// Sort the contents of this collection using a custom IComparer object.
        /// </summary>
        /// <param name="dir">A value from the SortDirection enumeration defining the order to sort into.</param>
        /// <param name="comparer">An instance of an object conforming to the IComparable interface that will be used to compare the objects.</param>
        protected virtual void Sort(SortDirection dir, IComparer comparer)
        {
            lock (_lockMe)
            {
                SortProgressEventArgs progArgs = null;
                if (this.Sorting != null)
                {
                    progArgs = new SortProgressEventArgs(0);
                }

                T[] vals = new T[this.InnerList.Count];
                for (int i = 0; i < this.InnerList.Count; i++)
                {
                    vals[i] = (T)this.InnerList[i];
                }
                if (progArgs != null)
                {
                    progArgs._pcntComp = ((33 / 100) * this.Count);
                    this.OnSorting(progArgs);
                }

                string[] keys = (string[])this._keys.ToArray(typeof(string));
                //Array.Sort<string, int>(keys, vals);

                Array.Sort(vals, keys, comparer);
                if (progArgs != null)
                {
                    progArgs._pcntComp = ((66 / 100) * this.Count);
                    this.OnSorting(progArgs);
                }

                if (dir == SortDirection.Descending)
                {
                    Array.Reverse(vals);
                    Array.Reverse(keys);
                }

                // This method will just "replace" all the existing data.
                for (int i = 0; i < keys.Length; i++)
                {
                    this._keys[i]     = keys[i];
                    this.InnerList[i] = vals[i];
                }
                if (progArgs != null)
                {
                    progArgs._pcntComp = ((66 / 100) * this.Count);
                    this.OnSorting(progArgs);
                }
            }
        }
        /// <summary>
        /// Sort the contents of this collection based on a public property exposed by the collection item, using the specified sort order.
        /// </summary>
        /// <param name="valueSortProperty">The name of the public property whose 'ToString()' value will be used for the sort.</param>
        /// <param name="dir">A value from the SortDirection enumeration defining the order to sort into.</param>
        protected virtual void Sort(string valueSortProperty, SortDirection dir)
        {
            lock (_lockMe)
            {
                SortProgressEventArgs progArgs = null;
                if (this.Sorting != null)
                {
                    progArgs = new SortProgressEventArgs(0);
                }

                if (this.InnerList.Count < 1)
                {
                    // If there aren't any items in the collection, then there's nothing
                    //   to do here.
                    return;
                }

                // Setup the binding flags for our Reflection search.
                System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.Public
                                                       | System.Reflection.BindingFlags.GetProperty
                                                       | System.Reflection.BindingFlags.SetProperty
                                                       | System.Reflection.BindingFlags.Instance
                                                       | System.Reflection.BindingFlags.Static;

                // We need two collections: one to hold the string values we're sorting
                //   on, and the other to hold the value keys.
                string[] valNms = new string[this.Count];
                string[] valKys = (string[])this._keys.ToArray(typeof(System.String[]));
                for (int i = 0; i < this.Count; i++)
                {
                    object itemVal = null;
                    if (!string.IsNullOrEmpty(valueSortProperty))
                    {
                        // The the caller specified a 'valueSortProperty', use Reflection
                        //   to try and find the property accessor on the current object.
                        Type t = this[i].GetType();
                        System.Reflection.PropertyInfo pnfo = t.GetProperty(valueSortProperty, flags);
                        if (pnfo != null)
                        {
                            // If we found it, get it's value for the sort.
                            itemVal = pnfo.GetValue(this[i], null);
                        }
                    }
                    // If we still haven't populated the 'itemVal' object with anything
                    //   yet, just get the current item's ToString() value.
                    if (itemVal == null)
                    {
                        itemVal = this[i].ToString();
                    }

                    // Add the found string to the array.
                    valNms[i] = itemVal.ToString();

                    if (progArgs != null && i % 10 == 0)
                    {
                        progArgs._pcntComp = (((i / 4) / 100) * this.Count);
                        this.OnSorting(progArgs);
                    }
                }
                // The 'Array' class will do the basic string sorting for us.
                Array.Sort <string, string>(valKys, valNms);
                if (progArgs != null)
                {
                    progArgs._pcntComp = ((50 / 100) * this.Count);
                    this.OnSorting(progArgs);
                }

                // Array.Sort always sorts ascending, so if the specified to have the
                //   items sorting in descending order, we need to reverse the contents
                //   of the valKys array.  NOTE: We're not going to use the valNms
                //   array again, so there's no reason to waste processor time
                //   reversing it also.
                if (dir == SortDirection.Descending)
                {
                    Array.Reverse(valKys);
                }

                // Now we've got two string arrays containing sorted values/keys, we
                //   need to offload our entire collection to a temp space to hold
                //   the "real" objects, since our value array only holds simple
                //   string values.
                ObjectCollection objCol = new ObjectCollection();
                for (int i = 0; i < this.Count; i++)
                {
                    objCol.Add(this[i], this.GetKey(i));
                }
                if (progArgs != null)
                {
                    progArgs._pcntComp = ((75 / 100) * this.Count);
                    this.OnSorting(progArgs);
                }

                // Now, we're going to clear the current collection.
                this.Clear();

                // ...And then rebuild it from our backup source.
                // NOTE: The key values array got reorganized along with the string
                //   values when we made the call to Array.Sort, so we really don't
                //   care about the string values anymore, only the physical object
                //   collection where we backed up the contents of this collection
                //   before we cleared it.
                for (int i = 0; i < valKys.Length; i++)
                {
                    this.Add(objCol[valKys[i]], valKys[i]);
                }
                if (progArgs != null)
                {
                    progArgs._pcntComp = ((100 / 100) * this.Count);
                    this.OnSorting(progArgs);
                }
            }
        }