3

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?

Migwell
  • 18,631
  • 21
  • 91
  • 160
  • 1
    You state the key (string) may change so it is not hard static key. If the data does not have a classic key then don't use a key, value collection (even one where the key is derived from a value). I would just use a List and use LINQ to sort. If the key is changing the mycolletion[key] just does not have as much utility and will throw an exception if the key is not found. At this point you are searching dynamic data and you can just use LINQ. – paparazzo Mar 24 '12 at 18:27

5 Answers5

2

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.

Community
  • 1
  • 1
Reddog
  • 15,219
  • 3
  • 51
  • 63
  • Does the AsBindable().OrderBy() order the current elements, or return an IEnumberable of the sorted elements? – Migwell Jan 12 '11 at 06:23
  • Yes - it outputs the elements in order when iterated. And yes - I believe because of how BindableLinq is internally written you should find it's storing copies of the elements in order too (i.e. pre-computed sorting). If you want the items to be _stored_ in order (in your root collection), that harks you back to my original answer of using a SortedDictionary or SortedList instead or else calling a sort algorithm on your input collection (http://www.codeproject.com/KB/recipes/cssorters.aspx). – Reddog Jan 12 '11 at 18:42
2

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!

Dan
  • 379
  • 3
  • 12
1

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.

RenniePet
  • 11,420
  • 7
  • 80
  • 106
1

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.

Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
-1

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.

Reddog
  • 15,219
  • 3
  • 51
  • 63
  • 2
    Another class *where the key is embedded in the value* – Migwell Jan 12 '11 at 00:34
  • Huh? The key used for sorting in SortedDictionary can be externally supplied or even "embedded" from the element - that is, it's specified on insertion. – Reddog Jan 12 '11 at 00:41
  • 1
    But from that point onwards, it is separate from the value. If I change the Node's value, I want it to change the Key. – Migwell Jan 12 '11 at 00:45