Sorting a ListView Data Source in WPF
The first that you need to do is define two data templates for the column headers, one indicating when the column is sorted ascending and the other indicating when the column is sorted descending. For example the templates could be:
<DataTemplate x:Key="HeaderTemplateDescending">
<DockPanel>
<TextBlock HorizontalAlignment="Center"
Text="{Binding}" />
<Path x:Name="arrow" StrokeThickness="1"
Fill="DarkGray" Data="M 5,10 L 15,10 L 10,5" />
</DockPanel>
</DataTemplate>
<DataTemplate x:Key="HeaderTemplateAscending">
<DockPanel>
<TextBlock HorizontalAlignment="Center"
Text="{Binding}"/>
<Path x:Name="arrow" StrokeThickness="1"
Fill="DarkGray" Data="M 5,5 L 10,10 L 15,5" />
</DockPanel>
</DataTemplate>
The next step is hook the Click event of the GridViewColumnHeader, it can be done using an attached event in the ListView. In the handler of this event we will get the current sort order of the clicked column and we will change the template of the column header depending on the sort order we need.
private void OnColumnHeaderClick(object sender, RoutedEventArgs e)
{
GridViewColumn column =
((GridViewColumnHeader)e.OriginalSource).Column;
if (lastColumnSorted != null)
{
lastColumnSorted.HeaderTemplate = null;
}
SortDescriptionCollection sorts = notes.Items.SortDescriptions;
RenderSort(sorts, column, GetSortDirection(sorts, column));
}
private void RenderSort(SortDescriptionCollection sorts,
GridViewColumn column, ListSortDirection direction)
{
column.HeaderTemplate =
(DataTemplate)notes.FindResource("HeaderTemplate" + direction);
Binding columnBinding = column.DisplayMemberBinding as Binding;
if (columnBinding != null)
{
sorts.Clear();
sorts.Add(new SortDescription(columnBinding.Path.Path, direction));
lastColumnSorted = column;
}
}
The complete code sample is here, and the sample using Linq.