Skip to main content

Sorting Data Items

The following page provides a list of examples that demonstrate how to sort data items.

note

All examples in this topic assume that the grid is bound to the Orders table of the Northwind database, unless stated otherwise.

Sorting data items

The following example demonstrates how to sort the data items in an ascending direction according to the values of the ShipCountry column.

  <Grid xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid">
<Grid.Resources>
<xcdg:DataGridCollectionViewSource x:Key="cvs_orders"
Source="{Binding Source={x:Static Application.Current},
Path=Orders}">
<xcdg:DataGridCollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="ShipCountry" Direction="Ascending"/>
</xcdg:DataGridCollectionViewSource.SortDescriptions>
</xcdg:DataGridCollectionViewSource>
</Grid.Resources>
<xcdg:DataGridControl x:Name="OrdersGrid"
ItemsSource="{Binding Source={StaticResource cvs_orders}}">
<xcdg:DataGridControl.Columns>
<xcdg:Column FieldName="ShipCountry" VisiblePosition="0"/>
</xcdg:DataGridControl.Columns>
</xcdg:DataGridControl>
</Grid>

Preventing sorting and grouping

The following example demonstrates how to bind a grid to the Orders table and prevent columns from being sorted and reordered and groups from being created or removed. By default, the ShipCountry and ShipCity columns will be sorted, grouped, and fixed.

  <Grid xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid"
xmlns:d="clr-namespace:System.Windows.Data;assembly=PresentationFramework"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase">
<Grid.Resources>
<xcdg:DataGridCollectionViewSource x:Key="cvs_orders"
Source="{Binding Source={x:Static Application.Current},
Path=Orders}">
<xcdg:DataGridCollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="ShipCountry" Direction="Ascending"/>
<scm:SortDescription PropertyName="ShipCity" Direction="Ascending"/>
</xcdg:DataGridCollectionViewSource.SortDescriptions>
<xcdg:DataGridCollectionViewSource.GroupDescriptions>
<xcdg:DataGridGroupDescription PropertyName="ShipCountry"/>
<xcdg:DataGridGroupDescription PropertyName="ShipCity"/>
</xcdg:DataGridCollectionViewSource.GroupDescriptions>
</xcdg:DataGridCollectionViewSource>
</Grid.Resources>
<xcdg:DataGridControl x:Name="OrdersGrid"
ItemsSource="{Binding Source={StaticResource cvs_orders}}">
<xcdg:DataGridControl.Columns>
<xcdg:Column FieldName="ShipCountry" VisiblePosition="0"/>
<xcdg:Column FieldName="ShipCity" VisiblePosition="1"/>
</xcdg:DataGridControl.Columns>
<xcdg:DataGridControl.View>
<xcdg:TableView FixedColumnCount="2" UseDefaultHeadersFooters="False">
<xcdg:TableView.FixedHeaders>
<DataTemplate>
<xcdg:GroupByControl AllowSort="False" AllowGroupingModification="False"/>
</DataTemplate>
<DataTemplate>
<xcdg:ColumnManagerRow AllowSort="False" AllowColumnReorder="False"/>
</DataTemplate>
</xcdg:TableView.FixedHeaders>
</xcdg:TableView>
</xcdg:DataGridControl.View>
</xcdg:DataGridControl>
</Grid>

Custom sorting

This example demonstrates how to create a custom group description by deriving from the DataGridGroupDescription class and overriding the GroupNameFromItem method. The custom group description will group items according to the first letter in the value received as a parameter. The example results in the group being present at initial loading; also, when removing and re-adding the group, the custom group description is not triggered. See below for an alternative approach to avoid this.

The implementation for the custom sort comparer assigned to the group description's SortComparer property is provided below.

  using System;
using System.Collections.Generic;
using System.Text;
using Xceed.Wpf.DataGrid;
using System.Collections;
namespace Xceed.Wpf.Documentation
{
public class AlphabeticalGroupDescription : DataGridGroupDescription
{
public AlphabeticalGroupDescription()
: base()
{
}
public AlphabeticalGroupDescription( string propertyName )
: base( propertyName )
{
}

public override object GroupNameFromItem( object item, int level,
System.Globalization.CultureInfo culture )
{
object value = base.GroupNameFromItem( item, level, culture );
try
{
string content = Convert.ToString( value );
value = content.ToUpper().Substring( 0, 1 );
}
catch( InvalidCastException )
{
}
return value;
}
}
}

The following code demonstrates how to use the custom group description by adding it to the DataGridCollectionViewSource's GroupDescriptions property.

<Grid xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid"
xmlns:local="clr-namespace:Xceed.Wpf.Documentation">
<Grid.Resources>
<local:ConsonantVowelComparer x:Key="consonantVowelComparer"/>
<xcdg:DataGridCollectionViewSource x:Key="cvs_orders"
Source="{Binding
Source={x:Static Application.Current},
Path=Orders}">
<xcdg:DataGridCollectionViewSource.GroupDescriptions>
<local:AlphabeticalGroupDescription PropertyName="ShipCountry"
SortComparer="{StaticResource consonantVowelComparer}"/>
</xcdg:DataGridCollectionViewSource.GroupDescriptions>
</xcdg:DataGridCollectionViewSource>
</Grid.Resources>
<xcdg:DataGridControl x:Name="OrdersGrid"
ItemsSource="{Binding Source={StaticResource cvs_orders}}"/>
</Grid>

The following code provides the implementation for the custom sort comparer that is used to sort, by vowels then consonants, the group descriptions create above.

  <Window.Resources>
<local:DateGroupDescription x:Key="myDateGroupDescription"
PropertyName="DateTimeFieldName" />
</Window.Resources>

[...]

<xcdg:DataGridControl.Columns>
<xcdg:Column FieldName="DateTimeFieldName"
GroupDescription="{StaticResource myDateGroupDescription}" />
</xcdg:DataGridControl.Columns>

Handling collection-changed events

The following example demonstrates how to subscribe to the CollectionChanged event of the DataGridCollectionView.SortDescriptions collection's INotifyCollectionChanged interface implementation to be notified when sorting applied to a grid's columns changes.

  protected override void OnInitialized( EventArgs e )
{
base.OnInitialized( e );
DataGridCollectionView view = this.OrdersGrid.ItemsSource as DataGridCollectionView;
( ( INotifyCollectionChanged )view.SortDescriptions ).CollectionChanged +=
new NotifyCollectionChangedEventHandler( this.SortCollectionChanged );
}
private void SortCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
{
Debug.WriteLine( "Sort changed" );
}

Providing a custom sort comparer

The following example demonstrates how to provide a custom sort comparer that sorts addresses. The AddressComparer class (provided below) will first sort addresses which begin with numeric values by street name and then civic number. Address that do not have a civic number will be sorted alphabetically.

  <Grid xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid"
xmlns:local="clr-namespace:Xceed.Wpf.Documentation">
<Grid.Resources>
<local:AddressComparer x:Key="addressComparer"/>
<xcdg:DataGridCollectionViewSource x:Key="cvs_orders"
Source="{Binding Source={x:Static Application.Current},
Path=Orders}"
AutoCreateItemProperties="False">
<xcdg:DataGridCollectionViewSource.ItemProperties>
<xcdg:DataGridItemProperty Name="ShipCountry" />
<xcdg:DataGridItemProperty Name="ShipCity" />
<xcdg:DataGridItemProperty Name="ShipAddress"
SortComparer="{StaticResource addressComparer}"/>
<xcdg:DataGridItemProperty Name="ShipVia" />
</xcdg:DataGridCollectionViewSource.ItemProperties>
</xcdg:DataGridCollectionViewSource>
</Grid.Resources>
<xcdg:DataGridControl x:Name="OrdersGrid"
ItemsSource="{Binding Source={StaticResource cvs_orders}}"/>
</Grid>

The following code provides the implementation of the AddressComparer class.

  using System;
using System.Collections;
using System.Data;
namespace Xceed.Wpf.Documentation
{
public class AddressComparer: IComparer
{
public AddressComparer()
{
}
int IComparer.Compare( object x, object y )
{
string stringX = ( string )x;
string stringY = ( string )y;
const string digits = "0123456789";
if( ( digits.IndexOf( stringX[ 0 ] ) >= 0 ) && ( digits.IndexOf( stringY[ 0 ] ) >= 0 ) )
{
int index = 0;
System.Text.StringBuilder xNumber = new System.Text.StringBuilder();
while( ( index < stringX.Length ) && ( digits.IndexOf( stringX[ index ] ) >= 0 ) )
{
xNumber.Append( stringX[ index ] );
index++;
}
index = 0;
System.Text.StringBuilder yNumber = new System.Text.StringBuilder();
while( ( index < stringY.Length ) && ( digits.IndexOf( stringY[ index ] ) >= 0 ) )
{
yNumber.Append( stringY[ index ] );
index++;
}
long xValue = long.Parse( xNumber.ToString() );
long yValue = long.Parse( yNumber.ToString() );
if( xValue > yValue )
return 1;
if( xValue < yValue )
return -1;
return stringX.CompareTo( stringY );
}
else
{
return stringX.CompareTo( stringY );
}
}
}
}