Filter Editor
- 10 minutes to read
The Filter Editor allows users to build complex filter criteria. A user can add any number of conditions that apply to individual fields and then use logical operators to build the composite filter expression.
Invoke the Filter Editor at Runtime
Users can invoke the Filter Editor in the following ways:
Right-click a column header and select Filter Editor…:
Click the Edit Filter button ( ) in the Filter Panel:
Tip
Set the DataViewBase.AllowFilterEditor property to false to prohibit users from invoking the Filter Editor.
To invoke the Filter Editor in code, call the DataViewBase.ShowFilterEditor method or the DataViewCommandsBase.ShowFilterEditor command:
<Button Content="Show Filter Editor" Command="{Binding Path=Commands.ShowFilterEditor, ElementName=view}" />
<!-- ... -->
<dxg:GridControl>
<dxg:GridControl.View>
<dxg:TableView x:Name="view" />
</dxg:GridControl.View>
</dxg:GridControl>
Invoke the Filter Editor at Design Time
You can use the Filter Editor to configure filter criteria at design time. Locate the GridControl‘s FilterString property in the Visual Studio Properties window and click the ellipsis button to invoke the editor.
Filter Editor UI
The Filter Editor displays filter criteria as a tree structure where nodes are filter conditions. The entire expression is organized as a tree where parent nodes are logical operators that link individual filter conditions.
Conditional Formatting Filters
You can filter data by applying Conditional Formatting rules. The Filter Editor displays available rules and indicates the number of records that meet rule conditions:
Aggregate Filters
You can use the Filter Editor to filter data by items in bound collection properties. Specify the DataViewBase.AllowFilterEditorAggregateOperands property to display aggregate operands:
The Filter Editor displays all aggregate operators when you set the AllowFilterEditorAggregateOperands property to Aggregate
or AggregateWithCondition
. Use the ColumnBase.AllowedAggregateFilters property to customize the operator list for the column:
<dxg:GridColumn FieldName="Genres" AllowedAggregateFilters="Exists, Count"/>
Customize the Filter Editor
Use the DataViewBase.FilterEditorTemplate property to specify a custom template. In the template, define the FilterEditorControl and handle its events.
Customize the Field List
The Filter Editor shows a list of the GridControl‘s fields. If the GridControl displays Bands, the Filter Editor shows fields in a hierarchical structure:
Tip
The FilterEditorControl.PropertySelectorMode property specifies whether to show fields in List or Tree mode.
Use the FilterEditorControl.QueryFields event to customize the field list. The following code sample shows how to add the ShipCountry, ShipCity, and ShipAddress fields to the Ship category:
<dxg:TableView x:Name="view">
<dxg:TableView.FilterEditorTemplate>
<DataTemplate>
<dxfui:FilterEditorControl QueryFields="OnQueryFields" />
</DataTemplate>
</dxg:TableView.FilterEditorTemplate>
</dxg:TableView>
void OnQueryFields(object sender, QueryFieldsEventArgs e) {
var shipCountry = e.Fields["ShipCountry"];
var shipCity = e.Fields["ShipCity"];
var shipAddress = e.Fields["ShipAddress"];
shipCountry.Caption = "Country";
shipCity.Caption = "City";
shipAddress.Caption = "Address";
e.Fields.Remove(shipCountry);
e.Fields.Remove(shipCity);
e.Fields.Remove(shipAddress);
var shipGroup = new FieldItem { Caption = "Ship" };
shipGroup.Children.Add(shipCountry);
shipGroup.Children.Add(shipCity);
shipGroup.Children.Add(shipAddress);
e.Fields.Add(shipGroup);
}
Customize the Operator List
Standard Operators
The Filter Editor shows a list of operators the selected field accepts. Use the FilterEditorControl.QueryOperators event to customize the operator list.
The code sample below removes all operators except Equals and Does not equal:
<dxg:TableView x:Name="view">
<dxg:TableView.FilterEditorTemplate>
<DataTemplate>
<dxfui:FilterEditorControl QueryOperators="OnQueryOperators" />
</DataTemplate>
</dxg:TableView.FilterEditorTemplate>
</dxg:TableView>
void OnQueryOperators(object sender, FilterEditorQueryOperatorsEventArgs e) {
if(e.FieldName == "OrderDate") {
e.Operators.Clear();
e.Operators.Add(new FilterEditorOperatorItem(FilterEditorOperatorType.Equal));
e.Operators.Add(new FilterEditorOperatorItem(FilterEditorOperatorType.NotEqual));
}
}
Custom Operators
You can use the FilterEditorControl.QueryOperators event to add custom operators. The example below adds the Last Years operator:
Create a custom function. Do one of the following:
Use the CustomFunctionFactory.Create method.
The CustomFunctionFactory is an extension of the DevExpress.Xpf.Grid.v24.1.Extensions.dll library. Refer to C:\Program Files\DevExpress 24.1\Components\Sources\XPF\DevExpress.Xpf.Grid\DevExpress.Xpf.Grid.Extensions\ for information on how extension methods work.
The CustomFunctionFactory.Create method allows you to create a custom function with a maximum of 4 operands.
Implement the ICustomFunctionOperator interface. Refer to the following topic for more information: Implementing Custom Functions.
const string CustomFunctionName = "LastYears"; var currentYear = DateTime.Now.Year; ICustomFunctionOperatorBrowsable customFunction = CustomFunctionFactory.Create(CustomFunctionName, (DateTime date, int threshold) => { return currentYear >= date.Year && currentYear - date.Year <= threshold; } );
Call the CriteriaOperator.RegisterCustomFunction method to register the custom function.
Create the FilterEditorOperatorItem and add it to the FilterEditorQueryOperatorsEventArgs.Operators collection. Specify the operator item’s edit settings to define its operands:
void OnQueryOperators(object sender, FilterEditorQueryOperatorsEventArgs e) { if(e.FieldName == "OrderDate") { // ... var customFunctionEditSettings = new BaseEditSettings[] { new TextEditSettings { MaskType = MaskType.Numeric, Mask = "D", MaskUseAsDisplayFormat = true } }; e.Operators.Add(new FilterEditorOperatorItem(CustomFunctionName, customFunctionEditSettings) { Caption = "Last Years" }); } }
Predefined Filters
You can specify Predefined Filters with the ColumnBase.PredefinedFilters property. The Filter Editor displays these filters in the Predefined filters submenu:
<dxg:GridColumn FieldName="UnitPrice">
<dxg:GridColumn.PredefinedFilters>
<dxfui:PredefinedFilterCollection>
<dxfui:PredefinedFilter Name="Less than 10" Filter="?p < 10" />
<dxfui:PredefinedFilter Name="Between 10 and 50" Filter="?p > 10 and ?p < 50" />
<dxfui:PredefinedFilter Name="Between 50 and 100" Filter="?p > 50 and ?p < 100" />
<dxfui:PredefinedFilter Name="Greater than 100" Filter="?p > 100" />
</dxfui:PredefinedFilterCollection>
</dxg:GridColumn.PredefinedFilters>
</dxg:GridColumn>
Tip
Topic: Predefined Filters
Customize Operand Template
The Filter Editor automatically creates operand editors based on the field and operator type. You can customize operand editors.
The following code sample specifies the TrackBarEdit as an operand for the Between and NotBetween operators:
Create a template for the operands. The following models depend on the operator type. Use their properties to bind to operand values in the template:
- ConstantFilterModel (for example, Is null, Is Yesterday)
- BinaryFilterModel (for example, Equals, Is greater than)
- TernaryFilterModel (for example, Is between, Is between dates)
- VariadicFilterModel (for example, Is any of, Is none of)
<UserControl.Resources> <DataTemplate x:Key="ternaryTemplate"> <dxe:TrackBarEdit Minimum="0" Maximum="300" MinWidth="120" TickPlacement="None" dxfui:FilterEditorNavigation.Index="0"> <dxe:TrackBarEdit.EditValue> <MultiBinding Converter="{local:TrackBarEditRangeConverter}"> <Binding Path="LeftValueItem.Value"/> <Binding Path="RightValueItem.Value"/> </MultiBinding> </dxe:TrackBarEdit.EditValue> <dxe:TrackBarEdit.StyleSettings> <dxe:TrackBarRangeStyleSettings /> </dxe:TrackBarEdit.StyleSettings> </dxe:TrackBarEdit> </DataTemplate> </UserControl.Resources>
public class TrackBarEditRangeConverter : BaseMultiValueConverter { public override object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { if(values.Length != 2) return new TrackBarEditRange(); return new TrackBarEditRange(GetApproptiateValue(values[0]), GetApproptiateValue(values[1])); } short GetApproptiateValue(object value) { if(value is int) return System.Convert.ToInt16(value); return value is short ? (short)value : (short)0; } public override object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { var trackBarEditRange = value as TrackBarEditRange; if(trackBarEditRange == null) return new object[] { (short)0, (short)0 }; return new object[] { (short)trackBarEditRange.SelectionStart, (short)trackBarEditRange.SelectionEnd }; } }
Handle the FilterEditorControl.QueryOperators event, get the operator, and assign the created template to the OperatorItemBase.OperandTemplate property.
<dxg:TableView x:Name="view"> <dxg:TableView.FilterEditorTemplate> <DataTemplate> <dxfui:FilterEditorControl QueryOperators="OnQueryOperators" /> </DataTemplate> </dxg:TableView.FilterEditorTemplate> </dxg:TableView>
void OnQueryOperators(object sender, FilterEditorQueryOperatorsEventArgs e) { if(e.FieldName == "Quantity") { var template = (DataTemplate)FindResource("ternaryTemplate"); e.Operators[FilterEditorOperatorType.Between].OperandTemplate = template; e.Operators[FilterEditorOperatorType.NotBetween].OperandTemplate = template; } }
Customize Operand Values
The Filter Editor displays only those operand values that meet the current filter criteria. To show all values in the operand list, set the DataControlBase.ShowAllTableValuesInFilterPopup property to true.
You can allow users to select date-time functions and fields as operand values:
Use the FilterEditorControl.QueryOperands event to specify available operand types:
<dxg:GridControl>
<dxg:GridControl.Columns>
<dxg:GridColumn FieldName="ProductName"/>
<dxg:GridColumn FieldName="RequiredDate"/>
<dxg:GridColumn FieldName="ShippedDate"/>
<dxg:GridColumn FieldName="ShipCountry"/>
<dxg:GridColumn FieldName="ShipCity"/>
<dxg:GridColumn FieldName="ShipAddress"/>
</dxg:GridControl.Columns>
<dxg:GridControl.View>
<dxg:TableView x:Name="view">
<dxg:TableView.FilterEditorTemplate>
<DataTemplate>
<dxfui:FilterEditorControl QueryOperands="FilterEditorControl_OnQueryOperands" />
</DataTemplate>
</dxg:TableView.FilterEditorTemplate>
</dxg:TableView>
</dxg:GridControl.View>
</dxg:GridControl>
void FilterEditorControl_OnQueryOperands(object sender, QueryOperandsEventArgs e) {
switch(e.FieldName) {
case "RequiredDate":
case "ShippedDate":
e.AllowPropertyOperand = true;
e.AllowDateTimeFunctionOperand = true;
e.AllowValueOperand = true;
break;
}
}
Use the FilterEditorControl.QueryDateTimeFunctions event to customize the list of date-time functions that are displayed when the DateTime function operand is selected.
Use the FilterEditorControl.QueryOperandFields event to customize the list of fields that are displayed when the Property operand is selected.
Prohibit Operations
Prohibit Group Types
Use the FilterEditorControl.QueryGroupTypes event to prohibit group types. The following code sample prohibits users from specifying the Or and NotOr logical operators:
<dxg:TableView x:Name="view">
<dxg:TableView.FilterEditorTemplate>
<DataTemplate>
<dxfui:FilterEditorControl QueryGroupTypes="OnQueryGroupTypes" />
</DataTemplate>
</dxg:TableView.FilterEditorTemplate>
</dxg:TableView>
void OnQueryGroupTypes(object sender, QueryGroupTypesEventArgs e) {
e.AllowNotAnd = false;
e.AllowNotOr = false;
}
Prohibit Group Operations
Use the FilterEditorControl.QueryGroupOperations event to prohibit group operations. The following code sample prohibits users from adding custom expressions:
<dxg:TableView x:Name="view">
<dxg:TableView.FilterEditorTemplate>
<DataTemplate>
<dxfui:FilterEditorControl QueryGroupOperations="OnQueryGroupOperations" />
</DataTemplate>
</dxg:TableView.FilterEditorTemplate>
</dxg:TableView>
void OnQueryGroupOperations(object sender, QueryGroupOperationsEventArgs e) {
e.AllowAddCustomExpression = false;
}
Prohibit Users from Removing Conditions
Use the FilterEditorControl.QueryConditionOperations event to prohibit users from removing conditions:
<dxg:TableView x:Name="view">
<dxg:TableView.FilterEditorTemplate>
<DataTemplate>
<dxfui:FilterEditorControl QueryConditionOperations="OnQueryConditionOperations" />
</DataTemplate>
</dxg:TableView.FilterEditorTemplate>
</dxg:TableView>
void OnQueryConditionOperations(object sender, QueryConditionOperationsEventArgs e) {
e.AllowRemoveCondition = false;
}
Standalone Filter Editor
A standalone FilterEditorControl is available.
Specify the FilterEditorControl.Context property to associate the FilterEditorControl with the GridControl‘s filter context:
- The FilterEditorControl retrieves values, filter criteria, format settings and other details from the GridControl‘s context.
- The FilterEditorControl applies filter criteria to the GridControl‘s context.
The filter criteria specified in the FilterEditorControl are not automatically applied to the GridControl. To apply the current filter criteria, call the FilterEditorControl.ApplyFilter method or the FilterEditorCommands.ApplyFilter command.
<dxg:GridControl x:Name="filterGrid" ... />
<!-- ... -->
<dxfui:FilterEditorControl x:Name="filterEditor"
Context="{Binding Path=FilteringContext, ElementName=filterGrid}"/>
<Button Content="Apply Filter"
Command="{Binding Commands.ApplyFilter, ElementName=filterEditor}" />
Tip
- When users edit filter conditions in the FilterEditorControl (for example, add/remove conditions, select a field/operator, specify a value), the FilterEditorControl.FilterChanged event occurs.
- Use the FilterEditorControl.Filter property to get the current filter criteria specified in the FilterEditorControl.
Legacy Filter Editor
To use the legacy Filter Editor:
- For a specific GridControl, set the DataViewBase.UseLegacyFilterEditor property to true.
- For all controls (GridControl, TreeListControl, and PivotGridControl) in the project, set the CompatibilitySettings.UseLegacyFilterEditor property to true.
Limitations
In Virtual Sources and Server Mode, record counts are not displayed (the default setting). To display record counts, handle the DataControlBase.CustomUniqueValues event. For Virtual Sources, you can alternatively handle the GetUniqueValues event.