Windows Presentation Foundation
How to: Sort a GridView Column When a Header Is Clicked

This example shows how to create a ListView control that implements a GridView view mode and sorts the data content when a user clicks a column header.

Example

The following example defines a GridView with three columns that bind to the Year, Month, and Day, properties of the DateTime structure.

XAML
<GridView>
  <GridViewColumn DisplayMemberBinding="{Binding Path=Year}" 
                  Header="Year"
                  Width="100"/>
  <GridViewColumn DisplayMemberBinding="{Binding Path=Month}" 
                  Header="Month"
                  Width="100"/>
  <GridViewColumn DisplayMemberBinding="{Binding Path=Day}" 
                  Header="Day"
                  Width="100"/>
</GridView>

The following example shows the data items that are defined as an ArrayList of DateTime objects. The ArrayList is defined as the ItemsSource for the ListView control.

XAML
<ListView.ItemsSource>
  <s:ArrayList>
    <p:DateTime>1993/1/1 12:22:02</p:DateTime>
    <p:DateTime>1993/1/2 13:2:01</p:DateTime>
    <p:DateTime>1997/1/3 2:1:6</p:DateTime>
    <p:DateTime>1997/1/4 13:6:55</p:DateTime>
    <p:DateTime>1999/2/1 12:22:02</p:DateTime>
    <p:DateTime>1998/2/2 13:2:01</p:DateTime>
    <p:DateTime>2000/2/3 2:1:6</p:DateTime>
    <p:DateTime>2002/2/4 13:6:55</p:DateTime>
    <p:DateTime>2001/3/1 12:22:02</p:DateTime>
    <p:DateTime>2006/3/2 13:2:01</p:DateTime>
    <p:DateTime>2004/3/3 2:1:6</p:DateTime>
    <p:DateTime>2004/3/4 13:6:55</p:DateTime>
  </s:ArrayList>
</ListView.ItemsSource>

The s and p identifiers in the XAML tags refer to namespace mappings that are defined in the metadata of the XAML page. The following example shows the metadata definition.

XAML
<Window      
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="ListViewSort.Window1"    
    xmlns:s="clr-namespace:System.Collections;assembly=mscorlib"
    xmlns:p="clr-namespace:System;assembly=mscorlib">

To sort the data according to the contents of a column, the example defines an event handler to handle the Click event that occurs when you press the column header button. The following example shows how to specify an event handler for the GridViewColumnHeader control.

XAML
<ListView x:Name='lv' Height="150" HorizontalAlignment="Center" 
  VerticalAlignment="Center" 
  GridViewColumnHeader.Click="GridViewColumnHeaderClickedHandler"
 >

The example defines the event handler so that the sort direction changes between ascending order and descending order each time you press the column header button. The following example shows the event handler.

C#
public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }

    GridViewColumnHeader _lastHeaderClicked = null;
    ListSortDirection _lastDirection = ListSortDirection.Ascending;

    void GridViewColumnHeaderClickedHandler(object sender,
                                            RoutedEventArgs e)
    {
        GridViewColumnHeader headerClicked =
              e.OriginalSource as GridViewColumnHeader;
        ListSortDirection direction;

        if (headerClicked != null)
        {
            if (headerClicked.Role != GridViewColumnHeaderRole.Padding)
            {
                if (headerClicked != _lastHeaderClicked)
                {
                    direction = ListSortDirection.Ascending;
                }
                else
                {
                    if (_lastDirection == ListSortDirection.Ascending)
                    {
                        direction = ListSortDirection.Descending;
                    }
                    else
                    {
                        direction = ListSortDirection.Ascending;
                    }
                }

                string header = headerClicked.Column.Header as string;
                Sort(header, direction);

                if (direction == ListSortDirection.Ascending)
                {
                    headerClicked.Column.HeaderTemplate =
                      Resources["HeaderTemplateArrowUp"] as DataTemplate;
                }
                else
                {
                    headerClicked.Column.HeaderTemplate =
                      Resources["HeaderTemplateArrowDown"] as DataTemplate;
                }

                // Remove arrow from previously sorted header
                if (_lastHeaderClicked != null && _lastHeaderClicked != headerClicked)
                {
                    _lastHeaderClicked.Column.HeaderTemplate = null;
                }


                _lastHeaderClicked = headerClicked;
                _lastDirection = direction;
            }
        }
    }

The following example shows the sorting algorithm that is called by the event handler to sort the data. The sort is performed by creating a new SortDescription structure.

C#
private void Sort(string sortBy, ListSortDirection direction)
{
    ICollectionView dataView =
      CollectionViewSource.GetDefaultView(lv.ItemsSource);

    dataView.SortDescriptions.Clear();
    SortDescription sd = new SortDescription(sortBy, direction);
    dataView.SortDescriptions.Add(sd);
    dataView.Refresh();
}

For the complete sample, see ListView That Sorts Data Sample.

See Also

Tasks

Concepts

Reference

Other Resources

Tags :


Community Content

BeWillingToShare
How to Change the Header (Label) of the Column

This example uses the header of the column to sort the view. But if this name is not the same as the path in the binding the application will not work.

Solution: use the path of the binding instead.

In the function GridViewColumnHeaderClickedHandler(object sender, RoutedEventArgs e) do the following:

Change this code snippet:

string header = headerClicked.Column.Header as string;


with...

System.Windows.Controls.GridViewColumn colum = headerClicked.Column; 

string header = ((System.Windows.Data.Binding)(colum.DisplayMemberBinding)).Path.Path;


It works for me in the context of binding my ListView to a DataSet.

- Khalid Rouane


ramzi-m3
How to Change the Header (Label) of the Column VB

editing

Tags : contentbug

BeWillingToShare
pointing to binding

Thanks Khalid for the advice,

it works when you point to binding path instead of header name,

Tags :

Todd Beaulieu
Namespace Requirements

Import the System.ComponentModel Namespace to get this working.

Also, it's a bit confusing to not have Xaml Intellisense know about "GridViewColumnHeader.Click", but if you paste the entire line in and then navigate to the event handler, all will work correctly.

GridViewColumnHeader.Click="GridViewColumnHeaderClickedHandler"

Tags :

Vaishnavi Subramanian
Cant Find Resources
I cant find the resource "HeaderTemplateArrowUp/Down". Besides it always sorts in ascending order only.
Tags :

Thomas Levesque
More flexible and reusable approach
Khalid, your solution is fine if the column content is defined with DisplayMemberBinding, but it's not always the case : it could be defined with a CellTemplate instead...

I wrote a more flexible and reusable solution, based on attached properties :
http://tomlev2.wordpress.com/2009/03/27/wpf-automatically-sort-a-gridview-when-a-column-header-is-clicked/
Tags :

Page view tracker