Learn more about Xceed DataGrid for WPF
The last time we looked at the DataGrid for WPF we had looked at Grouping and Sorting. Today let’s look at the Filtering options that the datagrid offers.
Filtering Options
The DataGrid for WPF offers 3 ways to set a filter:
- Native CollectionView Filtering (using the Filter parameter on the CollectionViewSource)
- Automatic Filtering (using the AutoFilterControl)
- Advanced Filtering (using the FilterRow)
Native CollectionView Filtering
The data items that are displayed in a grid can be filtered using the Filter property of the DataGridCollectionViewBase or the Filter event of the DataGridCollectionViewSourceBase to which it is bound.
<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}"
Filter="ShipViaFilter"/>
</Grid.Resources>
<xcdg:DataGridControl x:Name="OrdersGrid"
ItemsSource="{Binding Source={StaticResource cvs_orders}}"/>
</Grid>
private void ShipViaFilter( object sender, FilterEventArgs e )
{
object value = ( ( System.Data.DataRow )e.Item )[ "ShipVia" ];
if( ( value != null ) && ( value != DBNull.Value ) )
{
if( ( int )value == 3 )
{
e.Accepted = true;
}
else
{
e.Accepted = false;
}
}
}
To refilter the data items displayed in a view, the Refresh method can be called on the ItemsSource.
( ( DataGridCollectionView )this.OrdersGrid.ItemsSource ).Refresh();
Automatic Filtering
The DataGridCollectionView and DataGridDetailDescription classes support automatic filtering, which provides Excel-like end-user filtering according to the distinct values of each column. Automatic filtering can be enabled by setting the AutoFilterMode property to And or Or (None by default), indicating whether data items will be filtered according to all or at least one of the filtering criteria defined by each column’s auto-filter control. The DistinctValuesConstraint property can also be set to determine if the distinct values are to be filtered according to the result of previous auto-filtering operations.
Option1 : set in XAML
<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}"
AutoFilterMode="And"
DistinctValuesConstraint="Filtered"
AutoCreateItemProperties="False">
<xcdg:DataGridCollectionViewSource.ItemProperties>
<xcdg:DataGridItemProperty Name="ShipCountry"
Title="Country"/>
<xcdg:DataGridItemProperty Name="ShipCity"
Title="City"/>
<xcdg:DataGridItemProperty Name="ShipAddress"
Title="Address"/>
<xcdg:DataGridItemProperty Name="ShipPostalCode"
Title="Postal Code"/>
<xcdg:DataGridItemProperty Name="ShipName"
Title="Name"
CalculateDistinctValues="False"/>
<xcdg:DataGridItemProperty Name="OrderDate"
Title="Order Date"
CalculateDistinctValues="False"/>
<xcdg:DataGridItemProperty Name="Freight"
CalculateDistinctValues="False"/>
</xcdg:DataGridCollectionViewSource.ItemProperties>
</xcdg:DataGridCollectionViewSource>
</Grid.Resources>
<xcdg:DataGridControl x:Name="OrdersGrid"
ItemsSource="{Binding Source={StaticResource cvs_orders}}"/>
</Grid>
Opion 2: set in code-behind
DataGridCollectionView view = new DataGridCollectionView( Orders, typeof( System.Data.DataRow ), false, false );
view.AutoFilterMode = AutoFilterMode.And;
view.DistinctValuesConstraint = DistinctValuesConstraint.Filtered;
view.ItemProperties.Add( new DataGridItemProperty( "ShipCountry", typeof( string ) ) );
view.ItemProperties.Add( new DataGridItemProperty( "ShipCity", typeof( string ) ) );
view.ItemProperties.Add( new DataGridItemProperty( "ShipAddress", typeof( string ) ) );
view.ItemProperties.Add( new DataGridItemProperty( "ShipPostalCode", typeof( string ) ) );
DataGridItemProperty shipName = new DataGridItemProperty( "ShipName", typeof( string ) );
shipName.CalculateDistinctValues = false;
view.ItemProperties.Add( shipName );
DataGridItemProperty orderDate = new DataGridItemProperty( "OrderDate", typeof( DateTime ) );
orderDate.CalculateDistinctValues = false;
view.ItemProperties.Add( orderDate );
DataGridItemProperty freight = new DataGridItemProperty( "Freight", typeof( double ) );
freight.CalculateDistinctValues = false;
view.ItemProperties.Add( freight );
dataGridControl.ItemsSource = view;
Advanced Filtering
In addition to automatic filtering, the grid provides a FilterRow that allows users to specify a filter expression used by the DataGridCollectionView to filter data items. Filter expressions entered in FilterCell follow a specific syntax and rules. This may be cumbersome to learn for users, and this is where Advanced filtering comes to the rescue. Advanced filtering provides a UI interface to help users build filter expressions without the need to learn yet another syntax.
Advanced filtering can be enabled by setting the view’s AdvancedFilterMode property to one of the value other than None, which is the default value. The chosen mode indicates how the advanced filtering control is triggered. Note that it is possible to disable advanced filtering on a per column basis by setting the column’s AllowAdvancedFilter property to false (true by default), this will prevent the advanced filter control from being displayed for that column.
<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}" />
</Grid.Resources/>
<xcdg:DataGridControl x:Name="OrdersGrid"
ItemsSource="{Binding Source={StaticResource cvs_orders}}">
<xcdg:DataGridControl.Columns>
<xcdg:Column FieldName="ShipCountry"
AllowAdvancedFilter="False" />
</xcdg:DataGridControl.Columns>
<xcdg:DataGridControl.View>
<xcdg:TableflowView AdvancedFilterMode="Always" />
</xcdg:DataGridControl.View>
</xcdg:DataGridControl>
</Grid>
Custom Distinct Values
By default, the values that are displayed in the auto-filter drop down represent the distinct values as they are extracted from the underlying data source; however, custom distinct values can be provided for one or more item properties rather than the originally extracted distinct values by handling their QueryDistinctValue event and returning the custom value.
<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}"
AutoFilterMode="And"
DefaultCalculateDistinctValues="False">
<xcdg:DataGridCollectionViewSource.ItemProperties>
<xcdg:DataGridItemProperty Name="OrderDate"
QueryDistinctValue="DataGridItemProperty_QueryDistinctValue_Date"
CalculateDistinctValues="True"/>
<xcdg:DataGridItemProperty Name="RequiredDate"
QueryDistinctValue="DataGridItemProperty_QueryDistinctValue_Date"
CalculateDistinctValues="True" />
<xcdg:DataGridItemProperty Name="ShippedDate"
QueryDistinctValue="DataGridItemProperty_QueryDistinctValue_Date"
CalculateDistinctValues="True" />
<xcdg:DataGridItemProperty Name="Freight"
QueryDistinctValue="DataGridItemProperty_QueryDistinctValue_Range"
CalculateDistinctValues="True" />
</xcdg:DataGridCollectionViewSource.ItemProperties>
</xcdg:DataGridCollectionViewSource>
</Grid.Resources>
<xcdg:DataGridControl x:Name="OrdersGrid"
ItemsSource="{Binding Source={StaticResource cvs_orders}}"/>
</Grid>
private void DataGridItemProperty_QueryDistinctValue_Date( object sender, QueryDistinctValueEventArgs e )
{
if( e.DataSourceValue is DateTime )
{
e.DistinctValue = ( ( DateTime )e.DataSourceValue ).ToString( "MMMM" );
}
}
private void DataGridItemProperty_QueryDistinctValue_Range( object sender, QueryDistinctValueEventArgs e )
{
if( e.DataSourceValue is decimal )
{
decimal value = ( decimal )e.DataSourceValue;
if( value <= 100 )
{
e.DistinctValue = "0 - 100";
}
else if( value > 100 && value <= 500 )
{
e.DistinctValue = "101 - 500";
}
else
{
e.DistinctValue = "500+";
}
}
}
For more information, please refer to the documentation.