Overview
The WPF DataGrid control provides built-in column sorting out of the box. When CanUserSortColumns is set to true (the default), clicking a column header sorts the rows by that column. In this article we cover the essentials and explore patterns for customising sort behaviour.
Enabling Default Sorting
By default, every column in a DataGrid is sortable as long as its SortMemberPath can be resolved against the bound data source:
<DataGrid ItemsSource="{Binding Products}"
AutoGenerateColumns="False"
CanUserSortColumns="True">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" SortMemberPath="Name" />
<DataGridTextColumn Header="Price" Binding="{Binding Price}" SortMemberPath="Price" />
</DataGrid.Columns>
</DataGrid>
Clicking the Name header once sorts ascending; clicking again reverses to descending; a third click clears the sort.
Sorting via Code-Behind
You can trigger sorting programmatically by manipulating DataGrid.Items.SortDescriptions:
using System.ComponentModel;
dataGrid.Items.SortDescriptions.Clear();
dataGrid.Items.SortDescriptions.Add(
new SortDescription(nameof(Product.Price), ListSortDirection.Descending));
dataGrid.Items.Refresh();
Reset the column-header sort glyph too so the UI stays in sync:
foreach (var col in dataGrid.Columns)
col.SortDirection = null;
var priceCol = dataGrid.Columns.First(c => c.SortMemberPath == nameof(Product.Price));
priceCol.SortDirection = ListSortDirection.Descending;
Custom Sort Logic with ICollectionView
For complex scenarios — case-insensitive string sort, multi-level sort, or sorting computed properties — use ICollectionView.CustomSort:
var view = CollectionViewSource.GetDefaultView(dataGrid.ItemsSource);
view.CustomSort = Comparer<Product>.Create((a, b) =>
StringComparer.OrdinalIgnoreCase.Compare(a.Name, b.Name));
CustomSort takes precedence over SortDescriptions, so clear SortDescriptions first if you switch between the two approaches.
Summary
| Scenario | Recommended approach |
|---|---|
| Simple column sorting | CanUserSortColumns="True" (default) |
| Programmatic sort | SortDescriptions + update SortDirection |
| Custom sort logic | ICollectionView.CustomSort |
For most line-of-business apps the default mechanism covers the common cases. Reach for CustomSort only when the data requires special ordering that SortDescription cannot express.