I would like to enable live sorting of ListBox items bound to an ObservableCollection; I would also like to enable the live sorting exclusively via my XAML markup (if possible). As things stand, the list is properly sorted on application startup, but items are simply appended (not sorted) to the ListBox when new items are added to the ObservableCollection.
In my viewmodel I have the following public property:
public ObservableCollection<Equipment> EquipmentList { get; set; }
Equipment is an auto-generated class from Entity Framework which contains a public string property named 'Description'. This is my sort target.
My XAML has the following DataTemplate which is intended to enable the live sorting:
<DataTemplate x:Key="EquipmentDescriptionTemplate"
DataType="{x:Type e:Equipment}">
<DataTemplate.Resources>
<CollectionViewSource x:Key="SortedEquipmentList"
Source="{Binding Path=Description,
Mode=OneWay,
UpdateSourceTrigger=PropertyChanged}"
IsLiveSortingRequested="True">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Description"
Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
<CollectionViewSource.LiveSortingProperties>
<clr:String>Description</clr:String>
</CollectionViewSource.LiveSortingProperties>
</CollectionViewSource>
</DataTemplate.Resources>
<TextBlock Text="{Binding Path=Description}" />
</DataTemplate>
And finally the XAML ListBox item:
<ListBox x:Name="EquipmentList"
ItemsSource="{Binding Path=EquipmentList, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"
ItemTemplate="{StaticResource EquipmentDescriptionTemplate}"
IsSynchronizedWithCurrentItem="True"
SelectedItem="{Binding EquipmentSelection, UpdateSourceTrigger=PropertyChanged}"
Grid.ColumnSpan="2" Grid.Row="1" Margin="5,5,5,5"/>
There's a lot of extra attributes which I added in my desperate attempts to get the live sorting to work (when in doubt, guess wildly!). I've left them in so folks can see what I've tried, and snicker.
How do I enable live ListBox sorting via XAML?
You'll want to bind the ItemsSource to the CollectionViewSource, not to the underlying collection:
<ListBox x:Name="EquipmentList"
ItemsSource="{StaticResource SortedEquipmentList}"
...
/>
Place the CollectionViewSource somewhere above, in your page's resource dictionary. Bind its source to the underlying collection ("EquipmentList"):
<CollectionViewSource x:Key="SortedEquipmentList"
Source="{Binding EquipmentList.View}"
IsLiveSortingRequested="True">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Description" Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
<CollectionViewSource.LiveSortingProperties>
<clr:String>Description</clr:String>
</CollectionViewSource.LiveSortingProperties>
</CollectionViewSource>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With