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); } } }