Migwell
Migwell

Reputation: 20127

How do you sort a KeyedCollection<TKey, TItem>?

Basically I've got a KeyedCollection<string, CustomNode>, and I want to be able to sort the collection by the key (or preferably with a custom comparer).

If this isn't possible, can someone recommend another class where the key is embedded in the value that I can sort?

Upvotes: 3

Views: 3833

Answers (5)

RenniePet
RenniePet

Reputation: 11658

This is based on the link provided in the answer by Dan: http://social.msdn.microsoft.com/forums/en-US/netfxbcl/thread/56adc0f9-aa1b-4acf-8546-082bb01058f2/

   public class RequestTemplate : IComparable<RequestTemplate>
   {
      // This is the primary key for the object
      private Guid _guidNumber;

      // This is what a collection of these objects should be sorted by
      private string _buttonCaption = "";


      public Guid GuidNumber
      {
         get { return _guidNumber; }
         set { _guidNumber = value; }  // Setter only provided for deserialization usage
      }

      public string ButtonCaption
      {
         get { return _buttonCaption; }
         set { _buttonCaption = value; }
      }


      /// <summary>
      /// Method needed to allow sorting a collection of these objects.
      /// </summary>
      public int CompareTo(RequestTemplate other)
      {
         return string.Compare(this.ButtonCaption, other.ButtonCaption, 
                               StringComparison.CurrentCultureIgnoreCase);
      }
   }


   public class RequestTemplateKeyedCollection : KeyedCollection<Guid, RequestTemplate>
   {
      /// <summary>
      /// Sort the collection by sorting the underlying collection, accessed by casting the Items 
      /// property from IList to List.
      /// </summary>
      public void Sort()
      {
         List<RequestTemplate> castList = base.Items as List<RequestTemplate>;
         if (castList != null)
            castList.Sort();  // Uses default Sort() for collection items (RequestTemplate)
      }


      /// <summary>
      /// Method needed by KeyedCollection.
      /// </summary>
      protected override Guid GetKeyForItem(RequestTemplate requestTemplate)
      {
         return requestTemplate.GuidNumber;
      }
   }

Haven't tested it extensively yet, but it seems to work OK.

Upvotes: 1

Dan
Dan

Reputation: 377

Came this question while trying to solve a similar problem. If it is still relevant, I was able to implement Sort using the example here:

http://social.msdn.microsoft.com/forums/en-US/netfxbcl/thread/56adc0f9-aa1b-4acf-8546-082bb01058f2/

Basically involves sorting the underlying List of the collection. Worked like a charm for me.

Cheers!

Upvotes: 2

Justin Niessner
Justin Niessner

Reputation: 245429

KeyCollection<T> inherits from Collection<T> which implements IEnumerable so you should be able to use IEnumerable.OrderBy(). IEnumerable.OrderBy() also has an overload that allows you to supply a custom comparer.

Upvotes: 1

Reddog
Reddog

Reputation: 15579

Upon further information (see comments on answer above), a requirement is to keep the "set" sorted by a element's property after the property is edited.

In this case, you might take a look at BindableLinq (there are other similar frameworks too) and use the OrderBy statement implemented in there.

KeyedCollection<string, CustomNode> collection = /* from whereever */
collection.Items.AsBindable().OrderBy(c => c.PropertyOnCustomNode);

As long as your edited property raises a PropertyChanged event then it'll apply the re-ordering immediately. If you wish to change your collection, then ensure that the source collection implements INotifyCollectionChanged.

Upvotes: 2

Reddog
Reddog

Reputation: 15579

You might look at the SortedDictionary collection... But that'll come with added expense for item retrieval O(log N) as opposed to a KeyedCollection with O(1) retrieval.

Upvotes: -1

Related Questions