У меня следующий класс:
[DataContract]
public class Pair<TKey, TValue> : INotifyPropertyChanged, IDisposable
{
public Pair(TKey key, TValue value)
{
Key = key;
Value = value;
}
#region Properties
[DataMember]
public TKey Key
{
get
{ return m_key; }
set
{
m_key = value;
OnPropertyChanged("Key");
}
}
[DataMember]
public TValue Value
{
get { return m_value; }
set
{
m_value = value;
OnPropertyChanged("Value");
}
}
#endregion
#region Fields
private TKey m_key;
private TValue m_value;
#endregion
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
#endregion
#region IDisposable Members
public void Dispose()
{ }
#endregion
}
Который я вставил в ObservableCollection:
ObservableCollection<Pair<ushort, string>> my_collection =
new ObservableCollection<Pair<ushort, string>>();
my_collection.Add(new Pair(7, "aaa"));
my_collection.Add(new Pair(3, "xey"));
my_collection.Add(new Pair(6, "fty"));
В: Как мне отсортировать его по ключу?
Ответы:
Сортировку наблюдаемого и возврат того же отсортированного объекта можно выполнить с помощью метода расширения. Для больших коллекций следите за количеством уведомлений об изменении коллекции.
Я обновил свой код, чтобы повысить производительность и обработать дубликаты (спасибо nawfal за то, что он подчеркнул низкую производительность оригинала, хотя он хорошо работал на примере исходных данных). Наблюдаемое разделяется на левую отсортированную половину и правую несортированную половину, где каждый раз минимальный элемент (найденный в отсортированном списке) смещается в конец отсортированного раздела из несортированного. Худший случай O (n). По сути, это сортировка по выбору (вывод см. Ниже).
Использование: образец с наблюдателем (для простоты использован класс Person)
Подробная информация о ходе сортировки, показывающая, как поворачивается коллекция:
Класс Person реализует как IComparable, так и IEquatable, последний используется для минимизации изменений в коллекции, чтобы уменьшить количество возникающих уведомлений об изменениях.
Чтобы вернуть ObservableCollection, вызовите .ToObservableCollection в * sortedOC *, используя, например, [эту реализацию] [1].
**** orig answer - это создает новую коллекцию **** Вы можете использовать linq, как показано ниже в методе doSort. Быстрый фрагмент кода: производит
3: xey 6: fty 7: aaa
В качестве альтернативы вы можете использовать метод расширения для самой коллекции
источник
ObservableCollection
BinarySearch
вместоIndexOf
.Это простое расширение прекрасно сработало для меня. Я просто должен был убедиться, что
MyObject
это такIComparable
. Когда метод сортировки вызывается наблюдаемой коллекциейMyObjects
, тоCompareTo
метод наMyObject
называется, который вызывает мой логический метод сортировки. Хотя здесь нет всех наворотов, присущих остальным ответам, это именно то, что мне нужно.источник
return Utils.LogicalStringCompare(a.Title, b.Title);
вместоreturn string.Compare(a.Title, b.Title);
? @NeilWЯ нашел соответствующую запись в блоге, которая дает лучший ответ, чем здесь:
http://kiwigis.blogspot.com/2010/03/how-to-sort-obversablecollection.html
ОБНОВИТЬ
ObservableSortedList что @romkyns указывает в комментариях автоматически поддерживает порядок сортировки.
Однако обратите внимание на замечание
источник
Вы можете использовать этот простой метод:
Сортировать можно так:
Подробнее: http://jaider.net/2011-05-04/sort-a-observablecollection/
источник
ObservableCollection
привязаны к ItemSource выпадающих списков, и вы вообще не видите коллекцию. Кроме того, эта операция очистки и заполнения очень быстрая ... "медленная" может быть уже оптимизированной сортировкой. наконец, вы можете изменить этот код, чтобы реализовать свой метод перемещения,sortedlist
аsource
все остальное просто.Move
события, причем только для действительно перемещенных.WPF предоставляет живую сортировку из коробки с использованием
ListCollectionView
класса ...После завершения этой инициализации делать больше нечего. Преимущество перед пассивной сортировкой заключается в том, что ListCollectionView выполняет всю тяжелую работу прозрачным для разработчика способом. Новые элементы автоматически размещаются в правильном порядке сортировки. Любой класс, производный от
IComparer
T, подходит для свойства настраиваемой сортировки.См. ListCollectionView для документации и других функций.
источник
Мне понравился метод расширения пузырьковой сортировки в блоге Ричи выше, но я не обязательно хочу просто сортировать, сравнивая весь объект. Я чаще хочу отсортировать по определенному свойству объекта. Поэтому я изменил его, чтобы он принимал селектор ключей, как это делает OrderBy, чтобы вы могли выбрать, по какому свойству сортировать:
Который вы бы назвали так же, как вы бы вызывали OrderBy, за исключением того, что он будет отсортировать существующий экземпляр вашего ObservableCollection вместо возврата новой коллекции:
источник
OrderBy
а затем провести сравнение, чтобы выяснить фактическое изменение.Ответ @NielW - это правильный путь для реальной сортировки на месте. Я хотел добавить немного измененное решение, позволяющее обойтись без использования
IComparable
:теперь вы можете вызывать его, как и любой другой метод LINQ:
источник
if(!Ascending) sorted.Reverse();
непосредственно передfor
: D (и не нужно беспокоиться о памяти, этот метод Reverse не создает никаких новых объектов, он на месте наоборот)Я хотел бы добавить к ответу NeilW . Чтобы включить метод, похожий на orderby. Добавьте этот метод как расширение:
И используйте как:
источник
Вариант - это когда вы сортируете коллекцию на месте, используя алгоритм сортировки выбора . Элементы перемещаются на место с помощью
Move
метода. Каждый ход запускаетCollectionChanged
событие сNotifyCollectionChangedAction.Move
(а такжеPropertyChanged
с именем свойстваItem[]
).У этого алгоритма есть несколько хороших свойств:
CollectionChanged
запускаемых событий), почти всегда меньше, чем у других подобных алгоритмов, таких как сортировка вставкой и пузырьковая сортировка.Алгоритм довольно простой. Коллекция повторяется, чтобы найти наименьший элемент, который затем перемещается в начало коллекции. Процесс повторяется, начиная со второго элемента и так далее, пока все элементы не будут перемещены на свои места. Алгоритм не очень эффективен, но для всего, что вы собираетесь отображать в пользовательском интерфейсе, это не имеет значения. Однако по количеству перемещений он достаточно эффективен.
Вот метод расширения, который для простоты требует реализации в элементах
IComparable<T>
. В других вариантах используется символIComparer<T>
илиFunc<T, T, Int32>
.Сортировка коллекции - это просто вызов метода расширения:
источник
T
чтобы иметь возможность сортировки элементов в коллекции. Сортировка включает в себя концепцию большего и меньшего, и только вы можете определить, какProfileObject
она упорядочена. Чтобы использовать метод расширения, вам необходимо реализоватьIComparable<ProfileObject>
наProfileObject
. Другие альтернативы, как указано, указываютIComparer<ProfileObject>
или, соответственно,Func<ProfileObject, ProfileObject, int>
изменяют код сортировки.Чтобы немного улучшить метод расширения в ответе xr280xr, я добавил необязательный параметр bool, чтобы определить, идет ли сортировка по убыванию или нет. Я также включил предложение Карлоса П. в комментарий к этому ответу. См. Ниже.
источник
Вам нужно постоянно сортировать вашу коллекцию? При извлечении пар нужно, чтобы они всегда сортировались или только несколько раз (может быть, просто для представления)? Насколько большой, по вашему мнению, будет ваша коллекция? Есть много факторов, которые могут помочь вам выбрать метод ведьмы.
Если вам нужно, чтобы коллекция постоянно сортировалась, даже когда вы вставляете или удаляете элементы, и скорость вставки не является проблемой, возможно, вам следует реализовать что-то
SortedObservableCollection
вроде упомянутого @Gerrie Schenck или проверить эту реализацию .Если вам нужно, чтобы ваша коллекция была отсортирована всего на несколько раз, используйте:
Для сортировки коллекции потребуется некоторое время, но даже в этом случае это может быть лучшим решением в зависимости от того, что вы с ней делаете.
источник
Мой текущий ответ уже набрал наибольшее количество голосов, но я нашел лучший и более современный способ сделать это.
источник
Создайте новый класс
SortedObservableCollection
, создайте егоObservableCollection
и реализуйтеIComparable<Pair<ushort, string>>
.источник
Один из способов - преобразовать его в список, а затем вызвать Sort (), предоставив делегат сравнения. Что-то вроде:-
(непроверено)
источник
Думаю, это самое элегантное решение:
http://www.xamlplayground.org/post/2009/07/18/Use-CollectionViewSource-effectively-in-MVVM-applications.aspx
источник
Какого черта, я также добавлю быстро скомбинированный ответ ... он немного похож на некоторые другие реализации здесь, но я добавлю его в любом случае:
(почти не проверял, надеюсь, я себя не смущаю)
Сформулируем сначала несколько целей (мои предположения):
1) Необходимо сортировать
ObservableCollection<T>
на месте, поддерживать уведомления и т. Д.2) Не должно быть ужасно неэффективным (т.е. что-то близкое к стандартной "хорошей" эффективности сортировки)
источник
В моем случае ни один из этих ответов не сработал. Либо потому, что он портит привязку, либо требует так много дополнительного кода, что это своего рода кошмар, либо ответ просто не работает. Итак, я подумал, что вот еще один более простой ответ. Это намного меньше кода и остается той же наблюдаемой коллекцией с дополнительным методом типа this.sort. Дайте мне знать, есть ли причина, по которой я не должен делать это таким образом (эффективность и т. Д.)?
... Где ScoutItem - мой публичный класс. Просто казалось намного проще. Дополнительное преимущество: он действительно работает и не портит привязки, не возвращает новую коллекцию и т. Д.
источник
Хорошо, поскольку у меня возникли проблемы с получением ObservableSortedList для работы с XAML, я пошел дальше и создал SortingObservableCollection . Он унаследован от ObservableCollection, поэтому работает с XAML, и я тестировал его на 98% охват кода. Я использовал его в своих приложениях, но не обещаю, что в нем нет ошибок. Не стесняйтесь вносить свой вклад. Вот пример использования кода:
Это PCL, поэтому он должен работать с Windows Store, Windows Phone и .NET 4.5.1.
источник
new
все эти методы, если у кого-то есть более типизированный экземпляр, эти методы не будут вызываться. Вместо этогоoverride
каждый переопределяемый метод и измените их по мере необходимости или используйте запасной вариантbase.Method(...)
. Вам, например, даже не нужно беспокоиться,.Add
потому что это внутреннее использование.InsertItem
, поэтому, если.InsertItem
оно переопределено и настроено,.Add
не повлияет на порядок.Вот что я делаю с расширениями OC:
источник
Это сработало для меня, где-то давно нашел.
Использование:
источник
Мне нужно было сортировать по нескольким вещам, а не по одному. Этот ответ основан на некоторых других ответах, но допускает более сложную сортировку.
Когда вы его используете, передайте серию вызовов OrderBy / ThenBy. Как это:
источник
Я многому научился из других решений, но обнаружил пару проблем. Во-первых, некоторые зависят от IndexOf, который, как правило, работает довольно медленно для больших списков. Во-вторых, в моей ObservableCollection были объекты EF, и использование Remove, похоже, повредило некоторые свойства внешнего ключа. Может я что-то не так делаю.
В любом случае вместо удаления / вставки можно использовать A Move, но это вызывает некоторые проблемы с исправлением производительности.
Чтобы решить проблему с производительностью, я создаю словарь с отсортированными по IndexOf значениями. Чтобы поддерживать словарь в актуальном состоянии и сохранить свойства сущности, используйте подкачку, реализованную с двумя перемещениями, вместо одного, как это реализовано в других решениях.
Одно движение сдвигает индексы элементов между местоположениями, что делает словарь IndexOf недействительным. Добавление второго хода для реализации свопа восстанавливает местоположения.
источник
источник