Filter Panel and Filter Builder Dialog in Blazor Grid
- 16 minutes to read
The DevExpress Blazor Grid component includes a built-in filter panel and filter builder dialog. The panel displays the current filter condition and provides controls to temporarily disable or clear it. Users can click the condition to open the filter builder dialog, where they can edit and combine filter criteria for Grid columns.

[!demo[Filter Builder Customization]]
Add a Filter Panel
Assign Auto to FilterPanelDisplayMode to display the filter panel only when Grid data is filtered. To always display the filter panel, set the FilterPanelDisplayMode property to Always:
@inject NwindDataService NwindDataService
<DxGrid Data="Data"
FilterMenuButtonDisplayMode="GridFilterMenuButtonDisplayMode.Always"
FilterPanelDisplayMode="GridFilterPanelDisplayMode.Always">
<Columns>
<DxGridDataColumn FieldName="SalesPerson" Caption="Salesperson" />
<DxGridBandColumn Caption="Order">
<Columns>
<DxGridDataColumn FieldName="CompanyName" />
<DxGridDataColumn FieldName="OrderDate" Caption="Date" />
<DxGridBandColumn Caption="Product">
<Columns>
<DxGridDataColumn FieldName="ProductName" Caption="Name" />
<DxGridDataColumn FieldName="UnitPrice" DisplayFormat="c"
CaptionAlignment="GridTextAlignment.Right" />
</Columns>
</DxGridBandColumn>
<DxGridDataColumn FieldName="Quantity" />
</Columns>
</DxGridBandColumn>
</Columns>
</DxGrid>
@code {
object Data { get; set; }
protected override async Task OnInitializedAsync() {
var invoices = await NwindDataService.GetInvoicesAsync();
var customers = await NwindDataService.GetCustomersAsync();
Data = invoices.OrderBy(i => i.OrderDate).Join(customers, i => i.CustomerId, c => c.CustomerId,
(i, c) => { return new {
CompanyName = c.CompanyName,
SalesPerson = i.Salesperson,
UnitPrice = i.UnitPrice,
OrderDate = i.OrderDate,
ProductName = i.ProductName,
Quantity = i.Quantity
};
});
}
}

Customize the Filter Panel
Handle the CustomizeElement event to customize filter panel appearance. Check if e.ElementType is GridElementType.FilterPanel to determine whether the processed element is the filter panel.
The following code snippet customizes the filter panel’s border:
.custom-filter-panel {
border: 2px solid #1e90ff;
border-radius: 8px;
}

Open the Filter Builder Dialog
The filter builder dialog is a centralized viewer/editor for the Grid component’s filter conditions. To open this dialog, users can click the current filter criteria in the filter panel. Call the ShowFilterBuilder() method to open this dialog from code.

The following code snippet adds a toolbar button that opens the filter builder dialog:
@inject NwindDataService NwindDataService
<DxGrid @ref="Grid" Data="Data">
<Columns>
<DxGridDataColumn FieldName="SalesPerson" Caption="Salesperson" />
<DxGridBandColumn Caption="Order">
<Columns>
<DxGridDataColumn FieldName="CompanyName" />
<DxGridDataColumn FieldName="OrderDate" Caption="Date" />
<DxGridBandColumn Caption="Product">
<Columns>
<DxGridDataColumn FieldName="ProductName" Caption="Name" />
<DxGridDataColumn FieldName="UnitPrice" />
</Columns>
</DxGridBandColumn>
<DxGridDataColumn FieldName="Quantity" />
</Columns>
</DxGridBandColumn>
</Columns>
<ToolbarTemplate>
<DxToolbar ItemRenderStyleMode="ToolbarRenderStyleMode.Contained">
<Items>
<DxToolbarItem Alignment="ToolbarItemAlignment.Right"
Text="Filter Builder" RenderStyle="ButtonRenderStyle.Secondary"
Click="() => Grid.ShowFilterBuilder()" />
</Items>
</DxToolbar>
</ToolbarTemplate>
</DxGrid>
@code {
IGrid Grid { get; set; }
object Data { get; set; }
protected override async Task OnInitializedAsync() {
var invoices = await NwindDataService.GetInvoicesAsync();
var customers = await NwindDataService.GetCustomersAsync();
Data = invoices.OrderBy(i => i.OrderDate).Join(customers, i => i.CustomerId, c => c.CustomerId,
(i, c) => { return new {
CompanyName = c.CompanyName,
SalesPerson = i.Salesperson,
UnitPrice = i.UnitPrice,
OrderDate = i.OrderDate,
ProductName = i.ProductName,
Quantity = i.Quantity
};
});
}
}
Filter Builder Fields
Field Generation
The Grid automatically generates and configures available filter builder fields based on the following column settings:
The filter field hierarchy is based on the column band hierarchy. The following code snippets demonstrate how filter fields are generated based on Grid columns:
<Columns>
<DxGridDataColumn FieldName="CompanyName" />
<DxGridBandColumn Caption="Product">
<Columns>
<DxGridDataColumn FieldName="ProductName" Caption="Name" />
<DxGridDataColumn FieldName="UnitPrice" />
</Columns>
</DxGridBandColumn>
<DxGridDataColumn FieldName="CustomerId" Caption="Customer">
<EditSettings>
<DxComboBoxSettings Data="Customers" ValueFieldName="CustomerId" TextFieldName="DisplayText" />
</EditSettings>
</DxGridDataColumn>
</Columns>
<Fields>
<DxFilterBuilderField FieldName="CompanyName" Type="@typeof(string)" Caption="Company Name" />
<DxFilterBuilderField FieldName="Product" Caption="Product" AllowSelection="false">
<Fields>
<DxFilterBuilderField FieldName="ProductName" Type="@typeof(string)"
Caption="Name" CaptionFullPath="Product.Name" />
<DxFilterBuilderField FieldName="UnitPrice" Type="@typeof(decimal)"
Caption="Unit Price" CaptionFullPath="Product.Unit Price" />
</Fields>
<DxFilterBuilderField FieldName="CustomerId" Caption="Customer" Type="@typeof(int)">
<EditSettings>
<DxComboBoxSettings Data="Customers" ValueFieldName="CustomerId" TextFieldName="DisplayText" />
</EditSettings>
</DxFilterBuilderField>
</Fields>
Field Visibility
The Grid sets initial field visibility based on the corresponding column’s visibility. The filter builder dialog automatically updates field visibility once a user displays or hides a column. The dialog automatically hides filter fields generated for bands if these fields no longer contain visible children.
To display or hide a field permanently, set FilterBuilderFieldDisplayMode to Never/Always. The following code snippet hides the Company Name filter field:
@inject NwindDataService NwindDataService
<DxGrid Data="Data"
FilterPanelDisplayMode="GridFilterPanelDisplayMode.Always">
<Columns>
<DxGridDataColumn FieldName="SalesPerson" Caption="Salesperson" />
<DxGridBandColumn Caption="Order">
<Columns>
<DxGridDataColumn FieldName="CompanyName"
FilterBuilderFieldDisplayMode="GridColumnFilterBuilderFieldDisplayMode.Never" />
<DxGridDataColumn FieldName="OrderDate" Caption="Date" />
<DxGridBandColumn Caption="Product">
<Columns>
<DxGridDataColumn FieldName="ProductName" Caption="Name" />
<DxGridDataColumn FieldName="UnitPrice" DisplayFormat="c"
CaptionAlignment="GridTextAlignment.Right" />
</Columns>
</DxGridBandColumn>
<DxGridDataColumn FieldName="Quantity" />
</Columns>
</DxGridBandColumn>
</Columns>
</DxGrid>
@code {
object Data { get; set; }
protected override async Task OnInitializedAsync() {
var invoices = await NwindDataService.GetInvoicesAsync();
var customers = await NwindDataService.GetCustomersAsync();
Data = invoices.OrderBy(i => i.OrderDate).Join(customers, i => i.CustomerId, c => c.CustomerId,
(i, c) => { return new {
CompanyName = c.CompanyName,
SalesPerson = i.Salesperson,
UnitPrice = i.UnitPrice,
OrderDate = i.OrderDate,
ProductName = i.ProductName,
Quantity = i.Quantity
};
});
}
}
Filter Builder Template
Specify a FilterBuilderTemplate to apply the following customizations:
- Display custom filter fields
- Display custom content within the filter builder dialog
- Change settings of the integrated Filter Builder component
To use autogenerated fields in this template, call the context.RenderDefaultFields method within the Filter Builder component’s Fields tag.
The following code snippet customizes the filter builder dialog as follows:
- Displays the applied filter condition above the Filter Builder component
- Limits available logical operators to
AndandOr - Adds a Country filter field
@inject NwindDataService NwindDataService
<DxGrid Data="Data"
FilterMenuButtonDisplayMode="GridFilterMenuButtonDisplayMode.Always"
FilterPanelDisplayMode="GridFilterPanelDisplayMode.Always">
<Columns>
<DxGridDataColumn FieldName="SalesPerson" Caption="Salesperson">
<EditSettings>
<DxComboBoxSettings Data="Salespersons" />
</EditSettings>
</DxGridDataColumn>
<DxGridBandColumn Caption="Order">
<Columns>
<DxGridDataColumn FieldName="CompanyName" />
<DxGridDataColumn FieldName="OrderDate" Caption="Date" />
<DxGridBandColumn Caption="Product">
<Columns>
<DxGridDataColumn FieldName="ProductName" Caption="Name">
<EditSettings>
<DxComboBoxSettings Data="ProductNames" />
</EditSettings>
</DxGridDataColumn>
<DxGridDataColumn FieldName="UnitPrice" />
</Columns>
</DxGridBandColumn>
<DxGridDataColumn FieldName="Quantity" />
</Columns>
</DxGridBandColumn>
</Columns>
<FilterBuilderTemplate>
<b>Currently Applied Filter:</b> @(context.Grid.GetFilterCriteria()?.ToString() ?? "No filter")
<DxFilterBuilder @bind-FilterCriteria="context.FilterCriteria"
GroupOperatorTypes="[FilterBuilderGroupOperatorType.And, FilterBuilderGroupOperatorType.Or]">
<Fields>
@context.RenderDefaultFields()
<DxFilterBuilderField FieldName="ShipCountry" Caption="Country"
CaptionFullPath="Shipping Info.Country">
<EditSettings>
<DxComboBoxSettings Data="ShipCountries" />
</EditSettings>
</DxFilterBuilderField>
</Fields>
</DxFilterBuilder>
</FilterBuilderTemplate>
</DxGrid>
@code {
object Data { get; set; }
IEnumerable<string> Salespersons { get; set; }
IEnumerable<string> ProductNames { get; set; }
IEnumerable<string> ShipCountries { get; set; }
protected override async Task OnInitializedAsync() {
var invoices = await NwindDataService.GetInvoicesAsync();
var customers = await NwindDataService.GetCustomersAsync();
var invoiceList = invoices.ToList();
Salespersons = invoiceList.Select(i => i.Salesperson)
.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().OrderBy(s => s).ToList();
ProductNames = invoiceList.Select(i => i.ProductName)
.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().OrderBy(s => s).ToList();
ShipCountries = invoiceList.Select(i => i.ShipCountry)
.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().OrderBy(s => s).ToList();
Data = invoiceList.OrderBy(i => i.OrderDate).Join(customers, i => i.CustomerId, c => c.CustomerId,
(i, c) => { return new {
CompanyName = c.CompanyName,
SalesPerson = i.Salesperson,
UnitPrice = i.UnitPrice,
OrderDate = i.OrderDate,
ProductName = i.ProductName,
Quantity = i.Quantity,
ShipCountry = i.ShipCountry,
ShipCity = i.ShipCity,
ShipName = i.ShipName
};
});
}
}

Filter Synchronization
The Grid component automatically synchronizes filter changes across the following UI elements:
- Column filter menus
- Filter row
- Filter panel
- Filter builder dialog
Of these elements, only the filter panel and filter builder can display all filter conditions. Other elements have limitations, for example, column filter menus do not support the Contains operator, and filter row cells cannot display the Betweencondition. To ensure the entire filter expression is visible, add a filter panel to the Grid. The panel also provides access to the filter builder dialog.

Note
The Grid updates a column’s FilterRowOperatorType once users apply filters to column data using another UI element. For instance, after a user selects a filter menu value, the column’s FilterRowOperatorType switches to Equals. The operator type remains Equals even after the filter is cleared.
You can extend filter row UI and display filter operators for each column. Refer to the following example for additional information: Incorporate a selector for filter row operator type.