У меня есть наблюдаемая коллекция, и я сортирую ее с помощью linq. Все отлично, но проблема в том, как отсортировать реальную наблюдаемую коллекцию? Вместо этого у меня просто получается какая-то вещь IEnumerable, и я очищаю коллекцию и снова добавляю материал. Это не может быть хорошо для производительности. Кто-нибудь знает, как это сделать лучше?
6 ответов
Если вы используете Silverlight 3.0, то использование CollectionViewSource - самый чистый способ. См. Пример ниже: (это также можно сделать через xaml)
ObservableCollection<DateTime> ecAll = new ObservableCollection<DateTime>();
CollectionViewSource sortedcvs = new CollectionViewSource();
sortedcvs.SortDescriptions.Add(new System.ComponentModel.SortDescription("Date",
System.ComponentModel.ListSortDirection.Ascending));
sortedcvs.Source = ecAll;
ListBoxContainer.DataContext = sortedcvs;
И в соответствующем наборе xaml
ItemsSource="{Binding}"
Для ListBox или любого производного элемента управления ItemsControl
Поскольку коллекция не предоставляет никакого механизма Sort
, это, вероятно, наиболее практичный вариант. Вы можете реализовать сортировку вручную, используя Move
и т. Д., Но, вероятно, это будет медленнее, чем при использовании этого способа.
var arr = list.OrderBy(x => x.SomeProp).ToArray();
list.Clear();
foreach (var item in arr) {
list.Add(item);
}
Кроме того, вы можете рассмотреть возможность отмены привязки любых элементов пользовательского интерфейса во время сортировки (с помощью любого подхода), который вы платите только за повторную привязку один раз:
Интересно, что если бы это было BindingList<T>
, вы могли бы использовать RaiseListChangedEvents
, чтобы минимизировать количество уведомлений:
var arr = list.OrderBy(x => x).ToArray();
bool oldRaise = list.RaiseListChangedEvents;
list.RaiseListChangedEvents = false;
try {
list.Clear();
foreach (var item in arr) {
list.Add(item);
}
} finally {
list.RaiseListChangedEvents = oldRaise;
if (oldRaise) list.ResetBindings();
}
Обратите внимание, что в Linq вам предоставляется IEnumerable из вашего запроса, и этот запрос еще не выполнен . Следовательно, следующий код выполняет запрос только один раз, чтобы добавить его в ObservableCollection:
var query = from x in Data
where x.Tag == "Something"
select x;
foreach(var item in query)
MyObservableCollection.Add(item);
Взгляните на "OrderBy" расширение на IEnumerable:
foreach(var item in query.OrderBy(x => x.Name))
MyObservableCollection.Add(item);
ObservableCollections не предназначены для сортировки. Список можно сортировать, и это основной механизм, используемый ответом, ссылающимся на List.Sort (), но ObservableCollection не является производным от List, поэтому вам здесь не повезло. Imo, «правильное» решение - не пытаться отсортировать ObservableCollection, а реализовать ICollectionView и привязать его экземпляр к вашему элементу управления. Этот интерфейс добавляет методы для сортировки и имеет дополнительное преимущество, заключающееся в том, что он распознается элементами управления Silverlight (ну, теми, которые все равно его поддерживают, например DataGrid), поэтому сортировку можно использовать непосредственно из уровня пользовательского интерфейса. Этот вопрос может быть полезным:
Я перешел по ссылке, упомянутой в этом сообщении http://mokosh.co.uk/post/2009/08/04/how-to-sort-observablecollection/comment-page-1/#comment-75
Но возникают проблемы с его работой в Silverlight
Я создал свойство public SortableObservableCollection. Термины. Когда я вызываю Terms.Sort (новый TermComparer ()), записи по-прежнему отображаются в пользовательском интерфейсе без сортировки.
Могли бы некоторые предположить, что могло пойти не так. Благодарность
Я нашел это на CodePlex:
Хотя еще не использовал.
Стог
Похожие вопросы
Связанные вопросы
Новые вопросы
linq
Language Integrated Query (LINQ) - это компонент Microsoft .NET Framework, который добавляет собственные возможности запроса данных в языки .NET. При необходимости рассмотрите возможность использования более подробных тегов, например [linq-to-sql], [linq-to-entity] / [entity-framework] или [plinq]