Skip to main content

Filter Chart Data

  • 6 minutes to read

This document describes how to filter chart data at the chart control level, and create a filter UI.

DevExpress WPF Charts - Data Filtering Demo

Run Demo

Note

If you use large data sources and users should not change filtering and sorting parameters, we recommend that you filter and sort your data source at the data source level before it is visualized.

Specify a Filter String

The Series.FilterString property defines an expression used to filter series data. Use Criteria Language Syntax to create the filter expression.

The following example displays only data points whose ProductCategory is Automation:

a chart with an applied filter expression

<dxc:ChartControl x:Name="chart">
    <dxc:XYDiagram2D>
        <dxc:BarSideBySideSeries2D DisplayName="Sales" 
                                   x:Name="series"
                                   DataSource="{DXBinding 'new $local:DevAVSales().GetSalesByRegion()'}"
                                   ArgumentDataMember="Region"
                                   ValueDataMember="Sales" 
                                   FilterString="[ProductCategory]='Automation'" 
                                   LabelsVisibility="True"/>
        <dxc:XYDiagram2D.AxisX>
            <dxc:AxisX2D TickmarksMinorVisible="False">
                <dxc:AxisX2D.QualitativeScaleOptions>
                    <dxc:QualitativeScaleOptions GridLayoutMode="GridShiftedLabelCentered"/>
                </dxc:AxisX2D.QualitativeScaleOptions>
            </dxc:AxisX2D>
        </dxc:XYDiagram2D.AxisX>
    </dxc:XYDiagram2D>
</dxc:ChartControl>

Code-Behind (a data source):

Show code
using System.Data;
using System.Windows;
namespace FilterStringExample {
    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
        }
    }
    public class DevAVSales {
        public DataTable GetSalesByRegion() {
            DataTable table = new DataTable();
            table.Columns.AddRange(new DataColumn[] { new DataColumn("ProductCategory", typeof(string)),
                                          new DataColumn("Region", typeof(string)), 
                                          new DataColumn("Sales", typeof(decimal)) });
            table.Rows.Add("Video players", "Asia", 853D);
            table.Rows.Add("Video players", "Australia", 321D);
            table.Rows.Add("Video players", "Europe", 655D);
            table.Rows.Add("Video players", "North America", 1325D);
            table.Rows.Add("Video players", "South America", 653D);
            table.Rows.Add("Automation", "Asia", 172D);
            table.Rows.Add("Automation", "Australia", 255D);
            table.Rows.Add("Automation", "Europe", 981D);
            table.Rows.Add("Automation", "North America", 963D);
            table.Rows.Add("Automation", "South America", 123D);
            table.Rows.Add("Monitors", "Asia", 1011D);
            table.Rows.Add("Monitors", "Australia", 359D);
            table.Rows.Add("Monitors", "Europe", 721D);
            table.Rows.Add("Monitors", "North America", 565D);
            table.Rows.Add("Monitors", "South America", 532D);
            table.Rows.Add("Projectors", "Asia", 998D);
            table.Rows.Add("Projectors", "Australia", 222D);
            table.Rows.Add("Projectors", "Europe", 865D);
            table.Rows.Add("Projectors", "North America", 787D);
            table.Rows.Add("Projectors", "South America", 332D);
            table.Rows.Add("Televisions", "Asia", 1356D);
            table.Rows.Add("Televisions", "Australia", 232D);
            table.Rows.Add("Televisions", "Europe", 1323D);
            table.Rows.Add("Televisions", "North America", 1125D);
            table.Rows.Add("Televisions", "South America", 865D);
            return table;
        }
    }
}

You can use the following code to set the FilterString property at runtime:

series.FilterString = "[ProductCategory]='Automation'";

Set Filter Criteria

You can use the Series.FilterCriteria property instead of Series.FilterString to build and pass a filter expression. Use Criteria Operators to construct the filter expression.

Use CriteriaOperator‘s descendants to specify the FilterCriteria property. Refer to Criteria Operators for more information.

<dxc:ChartControl x:Name="chart">
    <dxc:XYDiagram2D>
        <dxc:BarSideBySideSeries2D x:Name="series"
                                    DisplayName="Sales" 
                                    DataSource="{DXBinding 'new $local:DevAVSales().GetSalesByRegion()'}"
                                    ArgumentDataMember="Region"
                                    ValueDataMember="Sales">
        </dxc:BarSideBySideSeries2D>
    </dxc:XYDiagram2D>
</dxc:ChartControl>

Code-Behind:

using DevExpress.Data.Filtering;
using DevExpress.Xpf.Charts;
using DevExpress.Xpf.Core;
using System.Data;
using System.Windows;
namespace FilterStringExample {
    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
            series.FilterCriteria = new BinaryOperator("ProductCategory", "Automation", BinaryOperatorType.Equal);
        }
    }
    public class DevAVSales {
        public DataTable GetSalesByRegion() {
            DataTable table = new DataTable();
            table.Columns.AddRange(new DataColumn[] { new DataColumn("ProductCategory", typeof(string)), 
                                                      new DataColumn("Region", typeof(string)), 
                                                      new DataColumn("Sales", typeof(decimal)) });
            table.Rows.Add("Video players", "Asia", 853D);
            table.Rows.Add("Video players", "Australia", 321D);
            table.Rows.Add("Video players", "Europe", 655D);
            table.Rows.Add("Video players", "North America", 1325D);
            table.Rows.Add("Video players", "South America", 653D);
            table.Rows.Add("Automation", "Asia", 172D);
            table.Rows.Add("Automation", "Australia", 255D);
            table.Rows.Add("Automation", "Europe", 981D);
            table.Rows.Add("Automation", "North America", 963D);
            table.Rows.Add("Automation", "South America", 123D);
            table.Rows.Add("Monitors", "Asia", 1011D);
            table.Rows.Add("Monitors", "Australia", 359D);
            table.Rows.Add("Monitors", "Europe", 721D);
            table.Rows.Add("Monitors", "North America", 565D);
            table.Rows.Add("Monitors", "South America", 532D);
            table.Rows.Add("Projectors", "Asia", 998D);
            table.Rows.Add("Projectors", "Australia", 222D);
            table.Rows.Add("Projectors", "Europe", 865D);
            table.Rows.Add("Projectors", "North America", 787D);
            table.Rows.Add("Projectors", "South America", 332D);
            table.Rows.Add("Televisions", "Asia", 1356D);
            table.Rows.Add("Televisions", "Australia", 232D);
            table.Rows.Add("Televisions", "Europe", 1323D);
            table.Rows.Add("Televisions", "North America", 1125D);
            table.Rows.Add("Televisions", "South America", 865D);
            return table;
        }
    }
}

Convert a Filter String to the Filter Criteria Expression

Call the CriteriaOperator.Parse method to convert a filter string to its CriteriaOperator equivalent as follows:

series.FilterCriteria = CriteriaOperator.Parse("[ProductCategory] = 'Automation'");

Obtain Filtered Series Points

A series contains only filtered points after a filter is applied to the series. Handle the ChartControl.BoundDataChanged event to access the chart diagram’s series collection.

<dxc:ChartControl x:Name="chart" BoundDataChanged="chart_BoundDataChanged">
using DevExpress.Xpf.Charts;

private void chart_BoundDataChanged(object sender, RoutedEventArgs e) {
    SeriesPointCollection filteredPoints = chart.Diagram.Series[0].Points;
}

Create the Filter UI

The following example shows how to use FilterBehavior and AccordionControl to create a UI that allows you to filter chart series data. To apply a filter, bind a series’ Series.FilterCriteria to the FilterBehavior.ActualFilterCriteria property value.

A custom data filter UI for a chart

<dx:ThemedWindow xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core" 
<!-- ... -->
                 xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
                 xmlns:dxfui="http://schemas.devexpress.com/winfx/2008/xaml/core/filteringui"
                 xmlns:dxc="http://schemas.devexpress.com/winfx/2008/xaml/charts"
                 xmlns:dxa="http://schemas.devexpress.com/winfx/2008/xaml/accordion"
                 <!-- ... -->
        <dxc:ChartControl Grid.Column="0" DataSource="{Binding GdpValues}" x:Name="chart">
        <!-- ... -->
            <dxc:XYDiagram2D SeriesDataMember="CountryName" >
                <dxc:XYDiagram2D.SeriesTemplate>
                    <dxc:BarSideBySideSeries2D ArgumentDataMember="Year" ValueDataMember="Value"
                                      FilterCriteria="{Binding ElementName=filterBehavior, Path=ActualFilterCriteria}"/>
                </dxc:XYDiagram2D.SeriesTemplate>
                <!-- ... -->
            </dxc:XYDiagram2D>
        </dxc:ChartControl>
        <dxa:AccordionControl Grid.Column="1" x:Name="accordion">
            <dxmvvm:Interaction.Behaviors>
                <dxfui:FilterBehavior x:Name="filterBehavior" ItemsSource="{Binding ElementName=chart, Path=DataSource}" />
            </dxmvvm:Interaction.Behaviors>
            <dxa:AccordionItem Header="Continent" IsExpanded="True">
                <dxfui:CheckedListFilterElement FieldName="ContinentName"
                                                ShowCounts="False"/>
            </dxa:AccordionItem>
            <dxa:AccordionItem Header="Country" IsExpanded="True">
                <dxfui:CheckedListFilterElement FieldName="CountryName" 
                                                Height="200" 
                                                ShowCounts="False"/>
            </dxa:AccordionItem>
            <dxa:AccordionItem Header="Year" IsExpanded="True">
                <dxfui:RangeFilterElement FieldName="Year"/>
            </dxa:AccordionItem>
            <dxa:AccordionItem Header="Value" IsExpanded="True">
                <dxfui:RangeFilterElement FieldName="Value"/>
            </dxa:AccordionItem>
        </dxa:AccordionControl>
    </Grid>
</dx:ThemedWindow>
using DevExpress.Xpf.Core;
// ...
    public class MainViewModel {
        public IEnumerable<GdpValue> GdpValues { get; private set; }

        public MainViewModel(XmlGdpValueProvider valueProvider) {
            GdpValues = valueProvider.GetValues();
        }
    }
    // ...
    public class GdpValue {
        public string ContinentName { get; set; }
        public string CountryName { get; set; }
        public double Value { get; set; }
        public int Year { get; set; }
    }

Refer to the following section for more information: FilterBehavior - Filter Elements and ChartControl.

See Also