Reputation: 1032
I originally posted this as a LINQ query - got it working and then realised I had a problem. You can't use LINQ queries to select/filter and order the items in a CollectionViewSource (why oh why didn't I check this first, why oh why isn't this possible?).
So, I am now trying to work out how to sort a filtered CollectionViewSource.
My CollectionViewSource is bound to an ObservableCollection(Of MediaItems). MediaItems contains a child/nested List(Of AdvertOptions).
The parent ObservableCollection(Of MediaItems) - class is structured as follows:
MediaItems
.ID (int)
.Src (string)
.Advert (bool)
.AdOptions As List(Of AdvertOptions)
.Counter (int)
AdvertOptions class consists of:
.Age (int)
.Gender (int)
.Priority (int)
I am filtering out any MediaItems that don't meet the following criteria:
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)
After the CollectionViewSource has been filtered, I need to sort the items based on two sort orders so the resulting CollectionViewSource items can be navigated through in my applicaiton using the CollectionViewSource navigation methods (MoveCurrentToX etc).
The sort order I need to apply is:
The way I am filtering is by using these functions:
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
Just for reference, I am adding the filter as follows:
Public AdvertisingDataView As CollectionViewSource
AddHandler AppLocal.AdvertisingDataView.Filter, AddressOf FilterByAdvertisement
AddHandler AppLocal.AdvertisingDataView.Filter, AddressOf FilterByAdvertisementOption
I now need to work out how to sort the filtered items. The problem is, CollectionViewSource seems to have limited support for sorting. I can easily sort the Counter using:
AdvertisingDataView.SortDescriptions.Add(New SortDescription("Counter", ListSortDirection.Ascending))
But that's my secondary sort - I want to Sort first by AdOptions.Priority (requires sub-selecting the right item), then by Counter.
I was wondering if creating Groups would help but can't work out if this will provide the sorting capability I'm looking for.
I have looked at the possibility of converting to a ListCollectionView instead of CollectionViewSource, then using a CustomSort but I can't work out how I could implement this and if it would also offer the capability I'm looking for given my primary sort is a value within a nested list.
Can anyone contribute to help me achieve my outcome?
Ben
Upvotes: 1
Views: 2878
Reputation: 249
I don't know how to write it in VB, but i can show you in c# how it's made:
YourListView = CollectionViewSource.GetDefaultView(tempListView
.OrderBy(x => x.FirstSorting)
.ThenBy(y => y.SecondSorting));
Look how to do the same in VB, and you will fix this.
You have a link right here - http://linqsamples.com/linq-to-objects/ordering/ThenBy-lambda-csharp
Good luck!
Upvotes: 0
Reputation: 81243
You can achieve multiple levels of sorting on the default view of your CollectionViewSource. There are essentially 3 types of views automatically generated by WPF, all deriving from the CollectionView base class:
You can always add to multiple SortDescriptor to the SortCollection of your default view like this -
ListCollectionView lcv =
(ListCollectionView)CollectionViewSource.GetDefaultView(myCollection);
lcv.SortDescriptions.Add(new SortDescription(…));
Refer to these links for further refernce -
Upvotes: 2