Подтвердить что ты не робот

Сортировка наблюдаемой коллекции с помощью linq

У меня есть наблюдаемая коллекция, и я сортирую ее с помощью linq. Все отлично, но проблема у меня есть, как мне сортировать фактическую наблюдаемую коллекцию? Вместо этого я просто заканчиваю кое-что IEnumerable, и я заканчиваю очистку коллекции и добавление материала обратно. Это не может быть хорошо для производительности. Кто-нибудь знает, как лучше это сделать?

4b9b3361

Ответ 1

Если вы используете 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

Ответ 2

Поскольку сборник не предоставляет никакого механизма 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();
    }

Ответ 3

Обратите внимание, что в 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);

Ответ 4

ObservableCollections не предназначены для сортировки. Список сортируется и что основной механизм, используемый в ответе, ссылается на List.Sort(), но ObservableCollection не является производным от List, поэтому вам не повезло. Imo, "правильное" решение - не пытаться сортировать ObservableCollection, а реализовывать ICollectionView и связывать экземпляр этого с вашим контролем. Этот интерфейс добавляет методы для сортировки и имеет дополнительное преимущество, которое его распознает элементы управления Silverlight (ну, в любом случае, такие как DataGrid), поэтому ваша сортировка может быть использована непосредственно из слоя пользовательского интерфейса. Этот вопрос может быть полезен:

Silverlight и icollectionview

Ответ 5

i следил за ссылкой, упомянутой в этом сообщении http://mokosh.co.uk/post/2009/08/04/how-to-sort-observablecollection/comment-page-1/#comment-75

но проблема с его работой в Silverlight

Я создал свойство public SortableObservableCollection Terms  Когда я вызываю Term.Sort(новый TermComparer()), записи по-прежнему отображаются несортированными в пользовательском интерфейсе

Может кто-нибудь предположить, что может пойти не так. спасибо