Skip to main content

Grouping Data Items

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

tip

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

Grouping data items

The following example demonstrates how to group the data items by the ShipCountry and ShipCity columns.

  <Grid 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.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>
</Grid>

Preventing group and sorting

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>

Defining a default group configuration

The following example demonstrates how to provide a default group configuration.

<Grid 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.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.DefaultGroupConfiguration>
<xcdg:GroupConfiguration>
<xcdg:GroupConfiguration.Footers>
<DataTemplate>
<xcdg:InsertionRow/>
</DataTemplate>
</xcdg:GroupConfiguration.Footers>
</xcdg:GroupConfiguration>
</xcdg:DataGridControl.DefaultGroupConfiguration>
</xcdg:DataGridControl>
</Grid>

Programmatically toggling group expansion

The following example demonstrates how to handle the PreviewMouseLeftButtonDown event on the GroupHeaderControl objects contained in the headers of the child groups to toggle the expansion state of child groups using the ToggleGroupExpansion method. The group whose state is to be toggled will be retrieved using the GetParentGroupFromItem method.

  <Grid 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.GroupDescriptions>
<xcdg:DataGridGroupDescription PropertyName="ShipCountry"/>
<xcdg:DataGridGroupDescription PropertyName="ShipCity"/>
</xcdg:DataGridCollectionViewSource.GroupDescriptions>
</xcdg:DataGridCollectionViewSource>
<Style TargetType="{x:Type xcdg:GroupHeaderControl}">
<EventSetter Event="PreviewMouseLeftButtonDown"
Handler="HeaderDown"/>
</Style>
</Grid.Resources>
<xcdg:DataGridControl x:Name="OrdersGrid"
ItemsSource="{Binding Source={StaticResource cvs_orders}}"/>
</Grid>

Custom grouping

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>

Changing the group-header text

The following example demonstrates how to change the information displayed in each GroupHeaderControl by creating an implicit DataTemplate targeting the Group data type.

<Grid 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.GroupDescriptions>
<xcdg:DataGridGroupDescription PropertyName="ShipCountry"/>
</xcdg:DataGridCollectionViewSource.GroupDescriptions>
</xcdg:DataGridCollectionViewSource>
<DataTemplate DataType="{x:Type xcdg:Group}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="The "/>
<TextBlock Text="{Binding Value}"/>
<TextBlock Text=" group contains "/>
<TextBlock Text="{Binding Items.Count}"/>
<TextBlock Text=" items."/>
</StackPanel>
</DataTemplate>
</Grid.Resources>
<xcdg:DataGridControl x:Name="OrdersGrid"
ItemsSource="{Binding Source={StaticResource cvs_orders}}"/>
</Grid>

Providing a group-configuration selector

The following example demonstrates how to provide a FieldNameGroupConfigurationSelector that will apply the defined group configuration to all groups that are created from the values of the column corresponding to the specified field name.

<Grid 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.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.GroupConfigurationSelector>
<xcdg:FieldNameGroupConfigurationSelector>
<xcdg:FieldNameGroupConfigurationSelectorItem FieldName="ShipCity">
<xcdg:FieldNameGroupConfigurationSelectorItem.GroupConfiguration>
<xcdg:GroupConfiguration>
<xcdg:GroupConfiguration.Footers>
<DataTemplate>
<xcdg:InsertionRow />
</DataTemplate>
</xcdg:GroupConfiguration.Footers>
</xcdg:GroupConfiguration>
</xcdg:FieldNameGroupConfigurationSelectorItem.GroupConfiguration>
</xcdg:FieldNameGroupConfigurationSelectorItem>
</xcdg:FieldNameGroupConfigurationSelector>
</xcdg:DataGridControl.GroupConfigurationSelector>
</xcdg:DataGridControl>
</Grid>

Creating a group-configuration selector

The following example demonstrates how to create a custom group-configuration selector that will return the appropriate group configuration depending on the number of items in a group. The implementation of the ItemCountGroupConfigurationSelector is provided below.

  <Grid 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.GroupDescriptions>
<xcdg:DataGridGroupDescription PropertyName="ShipCity" />
</xcdg:DataGridCollectionViewSource.GroupDescriptions>
</xcdg:DataGridCollectionViewSource>
</Grid.Resources>
<xcdg:DataGridControl x:Name="OrdersGrid"
ItemsSource="{Binding Source={StaticResource cvs_orders}}">
<xcdg:DataGridControl.GroupConfigurationSelector>
<local:ItemCountGroupConfigurationSelector MinItemCount="10" />
</xcdg:DataGridControl.GroupConfigurationSelector>
</xcdg:DataGridControl>
</Grid>

The following code provides the implementation of the ItemCountGroupConfigurationSelector.

    public class ItemCountGroupConfigurationSelector : GroupConfigurationSelector
{
public ItemCountGroupConfigurationSelector()
{
}
public ItemCountGroupConfigurationSelector( int minItemCount )
:base()
{
this.MinItemCount = minItemCount;
}
public override GroupConfiguration SelectGroupConfiguration( int groupLevel,
System.Windows.Data.CollectionViewGroup collectionViewGroup,
System.ComponentModel.GroupDescription groupDescription )
{
if( collectionViewGroup == null )
return base.SelectGroupConfiguration( groupLevel, collectionViewGroup, groupDescription );
GroupConfiguration groupConfiguration = new GroupConfiguration();
Style style = new Style( typeof( Xceed.Wpf.DataGrid.DataRow ) );
if( collectionViewGroup.ItemCount <= m_minItemCount ) // red
{
style.Setters.Add( new Setter( Xceed.Wpf.DataGrid.DataRow.BackgroundProperty, Brushes.Red ) );
}
else // green
{
style.Setters.Add( new Setter( Xceed.Wpf.DataGrid.DataRow.BackgroundProperty, Brushes.LightGreen ) );
}
groupConfiguration.ItemContainerStyle = style;
return groupConfiguration;
}
private int m_minItemCount = 0;
public int MinItemCount
{
get
{
return m_minItemCount;
}
set
{
if( value != m_minItemCount )
m_minItemCount = value;
}
}
}