Skip to content

DevExpress-Examples/wpf-data-grid-filter-columns-bound-to-collection-properties

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Data Grid for WPF - Filter Columns Bound to Collection Properties

The Genres column contains elements of the List<object> type. This example assigns collection editors to the column's cells and allows users to filter GridControl data against column values:

image

Implementation Details

Display and Edit Collection Values

The DevExpress WPF Editors library includes editors that allow your users to edit collections. In this example, the CheckedTokenComboBox editor is assigned to the Genres column:

image

<dxg:GridColumn FieldName="Genres"
                FilterPopupMode="Excel">
    <dxg:GridColumn.EditSettings>
        <dxe:ComboBoxEditSettings ItemsSource="{Binding Genres}"
                                  DisplayMember="Name">
            <dxe:ComboBoxEditSettings.StyleSettings>
                <dxe:CheckedTokenComboBoxStyleSettings FilterOutSelectedTokens="False"/>
            </dxe:ComboBoxEditSettings.StyleSettings>
        </dxe:ComboBoxEditSettings>
    </dxg:GridColumn.EditSettings>
</dxg:GridColumn>

Set the column's FilterPopupMode property to Excel to use the customizable Excel-style drop-down filter.

Refer to the following help topic for more information: Implement multi-select in DevExpress WPF Data Editors.

Populate the Column's Drop-down Filter with Collection Values

Perform the following actions in the DataViewBase.ShowFilterPopup event handler:

<dxg:GridControl ...>
    <dxmvvm:Interaction.Behaviors>
        <behaviors:FilterDropDownAggregateOperatorBehavior
            ColumnItemsSource="{Binding Genres}"/>
    </dxmvvm:Interaction.Behaviors>
</dxg:GridControl>
internal class FilterDropDownAggregateOperatorBehavior : Behavior<GridControl> {
    // ...
    private void View_ShowFilterPopup(object sender, FilterPopupEventArgs e) {
        if (e.Column.FieldName == CollectionColumnFieldName) {
            e.ExcelColumnFilterSettings.AllowedFilterTypes = DevExpress.Xpf.Grid.ExcelColumnFilterType.FilterValues;
            e.ExcelColumnFilterSettings.FilterItems = ColumnItemsSource;
        }
    }
}

Implement Filter Operations

Use the GridControl.SubstituteFilter event to update the grid filter:

<dxg:GridControl ...>
    <dxmvvm:Interaction.Behaviors>
        <behaviors:FilterDropDownAggregateOperatorBehavior 
            CollectionColumnFieldName="Genres" 
            DataItemId="Value" 
            ColumnItemsSource="{Binding Genres}"/>
    </dxmvvm:Interaction.Behaviors>
</dxg:GridControl>
internal class FilterDropDownAggregateOperatorBehavior : Behavior<GridControl> {
    // ...
    private void AssociatedObject_SubstituteFilter(object sender, DevExpress.Data.SubstituteFilterEventArgs e) {
        InToAggregatePatcher.FieldName = CollectionColumnFieldName;
        InToAggregatePatcher.DataItemId = DataItemId;
        e.Filter = InToAggregatePatcher.Patch(e.Filter);
    }
}

The ClientCriteriaLazyPatcherBase.AggregatesCommonProcessingBase descendant creates a new In filter operator. This operator allows users to filter the grid by the column's collection values:

public class InToAggregatePatcher : ClientCriteriaLazyPatcherBase.AggregatesCommonProcessingBase {
    public static string FieldName;
    public static string DataItemId;
    public static CriteriaOperator Patch(CriteriaOperator source) {
        return new InToAggregatePatcher().Process(source);
    }
    public override CriteriaOperator Visit(InOperator theOperator) {
        var result = (InOperator)base.Visit(theOperator);
        var property = result.LeftOperand as OperandProperty;
        if (property?.PropertyName == FieldName && result.Operands.All(c => c is OperandValue)) {
            var items = result.Operands.Cast<OperandValue>().Select(c => c.Value);
            var ItemValues = items.Select(item => new OperandValue(item.GetType().GetProperty(DataItemId).GetValue(item)));
            var inOperator = new InOperator(new OperandProperty(DataItemId), ItemValues);
            var newOperator = CriteriaOperator.Parse(FieldName + "[" + inOperator.ToString() + "]");
            return newOperator;
        }
        return result;
    }
}

Refer to the following help topic for more information: Traverse through and modify the CriteriaOperator instances.

Customize the Drop-down Filter

  • The SearchControlContainerStyle.Visibility property allows you to hide the search box from the popup.
  • The ServiceValueTemplate property is used to specify the text displayed in the Select All checkbox.

image

<Style x:Key="{dxgt:ExcelColumnFilterPopupThemeKey ResourceKey=SearchControlContainerStyle, IsThemeIndependent=True}" 
       TargetType="{x:Type Grid}">
    <Setter Property="Visibility" Value="Collapsed"/>
</Style>
<Style x:Key="{dxgt:ExcelColumnFilterPopupThemeKey ResourceKey=ValueColumnStyle, IsThemeIndependent=True}" 
       TargetType="{x:Type dxg:TreeListColumn}">
    <Setter Property="CellTemplateSelector">
        <Setter.Value>
            <dxg:ExcelColumnFilterCellTemplateSelector>
                <dxg:ExcelColumnFilterCellTemplateSelector.ServiceValueTemplate>
                    <DataTemplate>
                        <dxe:TextEdit EditValue="{Binding RowData.Row.DisplayValue, Mode=OneWay}"
                                      ShowBorder="False"/>
                    </DataTemplate>
                </dxg:ExcelColumnFilterCellTemplateSelector.ServiceValueTemplate>
            </dxg:ExcelColumnFilterCellTemplateSelector>
        </Setter.Value>
    </Setter>
</Style>

Refer to the following help topic for more information: Modify Theme Resources.

Files to Review

Documentation

About

Allow users to filter GridControl data against the column bound to a collection

Topics

Resources

License

Stars

Watchers

Forks