Как реализовать несколько уровней сортировки в CollectionViewSource

Первоначально я разместил это как запрос LINQ - он заработал, а затем понял, что у меня проблема. Вы не можете использовать запросы LINQ для выбора/фильтрации и упорядочения элементов в CollectionViewSource (почему, почему я не проверил это первым, почему это невозможно?).

Итак, теперь я пытаюсь понять, как сортировать отфильтрованный CollectionViewSource.

Мой CollectionViewSource привязан к ObservableCollection (Of MediaItems). MediaItems содержит дочерний/вложенный список (Of AdvertOptions).

Родительский класс ObservableCollection(Of MediaItems) структурирован следующим образом:

MediaItems
 .ID (int)
 .Src (string)
 .Advert (bool)
 .AdOptions As List(Of AdvertOptions)
 .Counter (int)

AdvertOptions class consists of:
 .Age (int)
 .Gender (int)
 .Priority (int)

Я отфильтровываю все MediaItems, которые не соответствуют следующим критериям:

MediaItems.Advert = true
AdOptions.Age = x (parameter within triggered function called to perform the filter/sort)
AdOptions.Gender = y (parameter within triggered function called to perform the filter/sort)

После того, как CollectionViewSource отфильтрован, мне нужно отсортировать элементы на основе двух порядков сортировки, чтобы полученные элементы CollectionViewSource можно было перемещать в моем приложении с помощью методов навигации CollectionViewSource (MoveCurrentToX и т. д.).

Порядок сортировки, который мне нужно применить, следующий:

  1. AdOptions.Priority (в порядке убывания)
  2. По счетчику (в порядке возрастания)

Я фильтрую, используя эти функции:

Public Shared Sub FilterByAdvertisement(ByVal Item As Object, ByVal e As FilterEventArgs)

    Dim MediaObjectItem As MediaObject = TryCast(e.Item, MediaObject)

    If Not MediaObjectItem.IsAdvertisingMedia = True Then

        e.Accepted = False

    End If

End Sub

Public Shared Sub FilterByAvertisementOption(ByVal Item As Object, ByVal e As FilterEventArgs)

    Dim MediaObjectItem As MediaObject = TryCast(e.Item, MediaObject)

    Dim Items = From m In MediaObjectItem.AdOptions Select m Where m.Age = Current.Age And m.Gender = Current.Gender
    If Items.Count = 0 Then

        e.Accepted = False

    End If

End Sub

Просто для справки, я добавляю фильтр следующим образом:

Public AdvertisingDataView As CollectionViewSource

AddHandler AppLocal.AdvertisingDataView.Filter, AddressOf FilterByAdvertisement
AddHandler AppLocal.AdvertisingDataView.Filter, AddressOf FilterByAdvertisementOption

Теперь мне нужно решить, как сортировать отфильтрованные элементы. Проблема в том, что CollectionViewSource, похоже, имеет ограниченную поддержку сортировки. Я могу легко отсортировать счетчик, используя:

AdvertisingDataView.SortDescriptions.Add(New SortDescription("Counter", ListSortDirection.Ascending))

Но это моя вторичная сортировка - я хочу сначала отсортировать по AdOptions.Priority (требуется дополнительный выбор правильного элемента), а затем по счетчику.

Мне было интересно, поможет ли создание групп, но я не могу понять, предоставит ли это возможность сортировки, которую я ищу.

Я рассмотрел возможность преобразования в ListCollectionView вместо CollectionViewSource, а затем с использованием CustomSort, но я не могу понять, как я мог бы это реализовать, и если бы он также предлагал возможность, которую я ищу, учитывая, что моя основная сортировка значение во вложенном списке.

Может ли кто-нибудь внести свой вклад, чтобы помочь мне достичь моего результата?

Бен


person Ben    schedule 12.11.2011    source источник


Ответы (2)


Вы можете добиться нескольких уровней сортировки в представлении по умолчанию вашего CollectionViewSource. По сути, существует 3 типа представлений, автоматически генерируемых WPF, и все они являются производными от базового класса CollectionView:

  • ListCollectionView -> Создается, когда коллекция реализует IList.
  • BindingListCollectionView -> Создается, когда коллекция реализует IBindingList.
  • EnumerableCollectionView -> Создается, когда коллекция не реализует ничего, кроме IEnumerable.

Вы всегда можете добавить несколько SortDescriptor в SortCollection вашего представления по умолчанию следующим образом:

ListCollectionView lcv =
(ListCollectionView)CollectionViewSource.GetDefaultView(myCollection);
lcv.SortDescriptions.Add(new SortDescription(…));

Обратитесь к этим ссылкам для дальнейшего ознакомления -

person Rohit Vats    schedule 12.11.2011
comment
Эй, спасибо за информацию. Один вопрос у меня есть с использованием SortDescriptor. Как я могу реализовать это, чтобы он сортировал, используя только один из элементов Priority во вложенном списке AdOptions? - person Ben; 13.11.2011
comment
Ссылки мертвы. - person DonBoitnott; 19.04.2021

Я не знаю, как это написать на VB, но могу показать на С#, как это делается:

YourListView = CollectionViewSource.GetDefaultView(tempListView
.OrderBy(x => x.FirstSorting)
.ThenBy(y => y.SecondSorting));

Посмотрите, как сделать то же самое в VB, и вы это исправите.

У вас есть ссылка прямо здесь - http://linqsamples.com/linq-to-objects/ordering/ThenBy-lambda-csharp

Удачи!

person BAndrei    schedule 02.04.2018