2011-01-12 3 views
3

В основном у меня есть KeyedCollection<string, CustomNode>, и я хочу, чтобы иметь возможность сортировать коллекцию с помощью ключа (или предпочтительно с помощью пользовательского сравнения).Как вы относитесь к KeyedCollection <TKey, TItem>?

Если это невозможно, может ли кто-то рекомендовать другой класс, в котором ключ встроен в значение, которое я могу сортировать?

+0

Вы указываете, что ключ (строка) может измениться, так что это не жесткий статический ключ. Если данные не имеют классического ключа, тогда не используйте ключ, набор значений (даже тот, где ключ получен из значения). Я бы просто использовал List и использовал LINQ для сортировки. Если ключ изменяет, mycolletion [key] просто не имеет такой же полезности и генерирует исключение, если ключ не найден. На этом этапе вы ищете динамические данные, и вы можете просто использовать LINQ. – Paparazzi

ответ

-1

Почему бы не просто использовать класс SortedList<TKey, TValue>?

MSDN link

+2

Поскольку KeyedCollection указывает значение ключа, а не заставляет вас явно добавлять его. –

+2

Это. Я сказал, что хочу, чтобы ключ был встроен. – Miguel

2

KeyCollection<T> наследует от Collection<T>, который реализует IEnumerable так что вы должны быть в состоянии использовать IEnumerable.OrderBy(). IEnumerable.OrderBy() также имеет перегрузку allows you to supply a custom comparer.

+4

OrderBy возвращает новую коллекцию, хотя она не сортирует текущую. – Miguel

-1

Вы можете посмотреть на коллекцию SortedDictionary ... Но это будет связано с дополнительными расходами на извлечение элементов O (log N), а не с помощью KeyedCollection с извлечением O (1).

+2

Другой класс *, где ключ встроен в значение * – Miguel

+0

А? Ключ, используемый для сортировки в SortedDictionary, может быть предоставлен извне или даже «встроен» из элемента, то есть указан в процессе вставки. – Reddog

+1

Но с этого момента он отделен от значения. Если я изменил значение Node, я хочу, чтобы он изменил Key. – Miguel

2

По дополнительной информации (см. Комментарии к answer выше), необходимо сохранить «набор», отсортированный по свойству элемента после редактирования свойства.

В этом случае вы можете взглянуть на BindableLinq (есть и другие подобные рамки) и использовать заявление OrderBy, реализованное там.

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

Пока отредактированное свойство вызывает событие PropertyChanged тогда он будет немедленно применить переупорядочивать. Если вы хотите изменить свою коллекцию, убедитесь, что исходная коллекция реализует INotifyCollectionChanged.

+0

Поддерживает ли AsBindable() OrderBy() текущие элементы или возвращает IEnumberable из отсортированных элементов? – Miguel

+0

Да - он выводит элементы в порядок при повторе. И да - я полагаю, из-за того, что BindableLinq внутренне написан, вы должны найти, что он также хранит копии элементов (например, предварительно вычисленная сортировка). Если вы хотите, чтобы элементы были _stored_ в порядке (в вашей корневой коллекции), это возвращает вас к первоначальному ответу на использование SortedDictionary или SortedList или же вызывает алгоритм сортировки в вашей коллекции ввода (http: //www.codeproject .com/KB/рецепты/cssorters.aspx). – Reddog

3

Пришел этот вопрос, пытаясь решить подобную проблему. Если он по-прежнему актуален, я был в состоянии осуществить сортировку по примеру здесь:

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

В основном включает в себя сортировке основного списка коллекции. Работала для меня как шарм.

Cheers!

1

Это основано на ссылке в ответ Дэн: 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; 
     } 
    } 

Не проверял еще широко, но это, кажется, работает нормально.

Смежные вопросы