Monday, December 16, 2013

Sorting Evolution (1) - Sorting a WPF ListView/GridView by clicking on the header

First Generation


Recently I wanted to sort a WPF ListView using GridView. I was using the MVVM pattern. After some searching and research, I used following XAML code in the View.

<ListView ItemsSource="{Binding FirstResultDataView}">
  <ListView.View>
    <GridView>
      <GridViewColumn DisplayMemberBinding="{Binding ResultNumber}">
        <GridViewColumnHeader Content="Number"
                              Command="{Binding SortCommand}"
                              CommandParameter="ResultNumber" />
      </GridViewColumn>
      <GridViewColumn DisplayMemberBinding="{Binding ResultOutput}">
        <GridViewColumnHeader Content="Output"
                              Command="{Binding SortCommand}"
                              CommandParameter="ResultOutput" />
      </GridViewColumn>
    </GridView>
  </ListView.View>
</ListView>

The ItemsSource is binded to the property FirstResultDataView in the ViewModel. The click event of each header is binded to the property SortCommand in the ViewModel by using RelayCommand. The CommandParameter is the property name of an element of the ItemsSource.

The method Sort is connected to the SortCommand in the constructor, so it is called after a header is clicked.

SortCommand = new RelayCommand(Sort);

Following C# code is used in the ViewModel. It displays the property that is binded to the ItemsSource in the View and the Sort method.

private ObservableCollection<ResultData> _firstResultData;
private CollectionViewSource _firstResultDataView;
private string _sortColumn;
private ListSortDirection _sortDirection;
 
public ICommand SortCommand
{
  get;
  private set;
}

public ObservableCollection<ResultData> FirstResultData
{
  get
  {
    return _firstResultData;
  }
  set
  {
    _firstResultData = value;
    _firstResultDataView = new CollectionViewSource();
    _firstResultDataView.Source = _firstResultData;
  }
}

public ListCollectionView FirstResultDataView
{
  get
  {
    return (ListCollectionView)_firstResultDataView.View;
  }
}

public void Sort(object parameter)
{
  string column = parameter as string;
  if (_sortColumn == column)
  {
    // Toggle sorting direction
    _sortDirection = _sortDirection == ListSortDirection.Ascending ?
                                       ListSortDirection.Descending :
                                       ListSortDirection.Ascending;
  }
  else
  {
    _sortColumn = column;
    _sortDirection = ListSortDirection.Ascending;
  }

  _firstResultDataView.SortDescriptions.Clear();
  _firstResultDataView.SortDescriptions.Add(
                           new SortDescription(_sortColumn, _sortDirection));
}

FirstResultDataView is the items source that is used in the view. It will be created if FirstResultData is set. The type of FirstResultDataView is ListCollectionView which can be used to sort, filter, or group data. It is derived from the View property of CollectionViewSource by setting the source property to FirstResultData.
The Sort method is called after a click on the column header is performed. It is adding a SortDescription to the CollectionViewSource. The SortDescription gets the column that is to sort and direction of sorting by using ListSortDirection.

With that code you get a ListView that can be sorted by clicking on the header. The first click set the sort direction to ascending the second click to descending.



The source code can be downloaded from http://code.msdn.microsoft.com/Sorting-a-WPF-ListView-by-209a7d45

Further Posts

  1. Sorting a WPF ListView/GridView by clicking on the header
  2. Sort Direction Indicators 
  3. Sort in ViewModel 
  4. Sort Direction Indicators with Adorners
  5. Reusability
  6. More Reusability
  7. Attached Property
  8. Behaviors (Expression Blend)

1 comment: