如何为DX Grid表格的筛选行添加自定义筛选选项
在Blazor DevExpress Grid筛选行添加自定义筛选操作下拉菜单
要为DX Grid的筛选行添加包含指定操作的下拉菜单,你需要为每个文本列自定义筛选行模板,并结合DevExpress的筛选API实现逻辑。以下是具体实现步骤:
1. 定义筛选操作枚举
在@code块中创建枚举,统一管理所有筛选操作:
public enum FilterOperation { BeginsWith, Contains, DoesNotContain, EndsWith, Equals, DoesNotEqual }
2. 为每个列声明筛选状态变量
为需要自定义筛选的列分别存储当前选中的筛选操作和输入值:
private FilterOperation _brandCodeFilterOp = FilterOperation.Contains; private string _brandCodeFilterValue = string.Empty; private FilterOperation _brandNameFilterOp = FilterOperation.Contains; private string _brandNameFilterValue = string.Empty; private FilterOperation _brandSecondaryCodeFilterOp = FilterOperation.Contains; private string _brandSecondaryCodeFilterValue = string.Empty;
3. 自定义列的筛选行模板
修改Columns中的每个文本列,添加FilterRowCellTemplate,嵌入下拉选择框和输入框:
<Columns> <DxGridCommandColumn /> <DxGridDataColumn FieldName="brand_code_365" Caption="Brand Code"> <FilterRowCellTemplate> <div class="d-flex"> <DxComboBox Data="@Enum.GetValues<FilterOperation>()" @bind-Value="@_brandCodeFilterOp" CssClass="me-2" Width="150px"> <ItemTemplate> @context switch { FilterOperation.BeginsWith => "Begins with(开头为)", FilterOperation.Contains => "Contains(包含)", FilterOperation.DoesNotContain => "Doesn't contain(不包含)", FilterOperation.EndsWith => "Ends with(结尾为)", FilterOperation.Equals => "Equals(等于)", FilterOperation.DoesNotEqual => "Doesn't equal(不等于)", _ => "" } </ItemTemplate> </DxComboBox> <DxTextBox @bind-Value="@_brandCodeFilterValue" Input="@(e => ApplyColumnFilter("brand_code_365", _brandCodeFilterOp, _brandCodeFilterValue))" CssClass="flex-grow-1"/> </div> </FilterRowCellTemplate> </DxGridDataColumn> <DxGridDataColumn FieldName="brand_name" Caption="Brand Name"> <FilterRowCellTemplate> <div class="d-flex"> <DxComboBox Data="@Enum.GetValues<FilterOperation>()" @bind-Value="@_brandNameFilterOp" CssClass="me-2" Width="150px"> <ItemTemplate> @context switch { FilterOperation.BeginsWith => "Begins with(开头为)", FilterOperation.Contains => "Contains(包含)", FilterOperation.DoesNotContain => "Doesn't contain(不包含)", FilterOperation.EndsWith => "Ends with(结尾为)", FilterOperation.Equals => "Equals(等于)", FilterOperation.DoesNotEqual => "Doesn't equal(不等于)", _ => "" } </ItemTemplate> </DxComboBox> <DxTextBox @bind-Value="@_brandNameFilterValue" Input="@(e => ApplyColumnFilter("brand_name", _brandNameFilterOp, _brandNameFilterValue))" CssClass="flex-grow-1"/> </div> </FilterRowCellTemplate> </DxGridDataColumn> <DxGridDataColumn FieldName="brand_secondary_code" Caption="Brand Secondary Code"> <FilterRowCellTemplate> <div class="d-flex"> <DxComboBox Data="@Enum.GetValues<FilterOperation>()" @bind-Value="@_brandSecondaryCodeFilterOp" CssClass="me-2" Width="150px"> <ItemTemplate> @context switch { FilterOperation.BeginsWith => "Begins with(开头为)", FilterOperation.Contains => "Contains(包含)", FilterOperation.DoesNotContain => "Doesn't contain(不包含)", FilterOperation.EndsWith => "Ends with(结尾为)", FilterOperation.Equals => "Equals(等于)", FilterOperation.DoesNotEqual => "Doesn't equal(不等于)", _ => "" } </ItemTemplate> </DxComboBox> <DxTextBox @bind-Value="@_brandSecondaryCodeFilterValue" Input="@(e => ApplyColumnFilter("brand_secondary_code", _brandSecondaryCodeFilterOp, _brandSecondaryCodeFilterValue))" CssClass="flex-grow-1"/> </div> </FilterRowCellTemplate> </DxGridDataColumn> </Columns>
4. 实现筛选逻辑方法
添加ApplyColumnFilter方法,根据选中的操作和输入值生成筛选条件并应用到Grid:
private void ApplyColumnFilter(string fieldName, FilterOperation op, string value) { if (string.IsNullOrWhiteSpace(value)) { Grid.ClearColumnFilter(fieldName); return; } var criteria = op switch { FilterOperation.BeginsWith => CriteriaOperator.Parse($"{fieldName} Like ?", $"{value}%"), FilterOperation.Contains => CriteriaOperator.Parse($"{fieldName} Like ?", $"%{value}%"), FilterOperation.DoesNotContain => CriteriaOperator.Parse($"Not ({fieldName} Like ?)", $"%{value}%"), FilterOperation.EndsWith => CriteriaOperator.Parse($"{fieldName} Like ?", $"%{value}"), FilterOperation.Equals => CriteriaOperator.Parse($"{fieldName} = ?", value), FilterOperation.DoesNotEqual => CriteriaOperator.Parse($"{fieldName} != ?", value), _ => null }; if (criteria != null) { Grid.SetColumnFilter(fieldName, criteria); } }
5. 引入必要命名空间
在页面顶部添加DevExpress筛选相关的命名空间:
@using DevExpress.Data.Filtering
完整修改后代码
@page "/" @using Data @using Newtonsoft.Json @using System.Net.Http.Json @using System.Net.Http @using System.Text @using System.Web @using Newtonsoft.Json.Linq @using DevExpress.Blazor @using DevExpress.Data.Filtering @using GlobalVariables @attribute [StreamRendering(true)] @rendermode InteractiveServer <DxGrid @ref = "Grid" Data="@BrandsData.list_brands" ShowSearchBox="true" ShowFilterRow="true" FilterMenuButtonDisplayMode="GridFilterMenuButtonDisplayMode.Always" EditMode="GridEditMode.EditRow" KeyboardNavigationEnabled="true"> <Columns> <DxGridCommandColumn /> <DxGridDataColumn FieldName="brand_code_365" Caption="Brand Code"> <FilterRowCellTemplate> <div class="d-flex"> <DxComboBox Data="@Enum.GetValues<FilterOperation>()" @bind-Value="@_brandCodeFilterOp" CssClass="me-2" Width="150px"> <ItemTemplate> @context switch { FilterOperation.BeginsWith => "Begins with(开头为)", FilterOperation.Contains => "Contains(包含)", FilterOperation.DoesNotContain => "Doesn't contain(不包含)", FilterOperation.EndsWith => "Ends with(结尾为)", FilterOperation.Equals => "Equals(等于)", FilterOperation.DoesNotEqual => "Doesn't equal(不等于)", _ => "" } </ItemTemplate> </DxComboBox> <DxTextBox @bind-Value="@_brandCodeFilterValue" Input="@(e => ApplyColumnFilter("brand_code_365", _brandCodeFilterOp, _brandCodeFilterValue))" CssClass="flex-grow-1"/> </div> </FilterRowCellTemplate> </DxGridDataColumn> <DxGridDataColumn FieldName="brand_name" Caption="Brand Name"> <FilterRowCellTemplate> <div class="d-flex"> <DxComboBox Data="@Enum.GetValues<FilterOperation>()" @bind-Value="@_brandNameFilterOp" CssClass="me-2" Width="150px"> <ItemTemplate> @context switch { FilterOperation.BeginsWith => "Begins with(开头为)", FilterOperation.Contains => "Contains(包含)", FilterOperation.DoesNotContain => "Doesn't contain(不包含)", FilterOperation.EndsWith => "Ends with(结尾为)", FilterOperation.Equals => "Equals(等于)", FilterOperation.DoesNotEqual => "Doesn't equal(不等于)", _ => "" } </ItemTemplate> </DxComboBox> <DxTextBox @bind-Value="@_brandNameFilterValue" Input="@(e => ApplyColumnFilter("brand_name", _brandNameFilterOp, _brandNameFilterValue))" CssClass="flex-grow-1"/> </div> </FilterRowCellTemplate> </DxGridDataColumn> <DxGridDataColumn FieldName="brand_secondary_code" Caption="Brand Secondary Code"> <FilterRowCellTemplate> <div class="d-flex"> <DxComboBox Data="@Enum.GetValues<FilterOperation>()" @bind-Value="@_brandSecondaryCodeFilterOp" CssClass="me-2" Width="150px"> <ItemTemplate> @context switch { FilterOperation.BeginsWith => "Begins with(开头为)", FilterOperation.Contains => "Contains(包含)", FilterOperation.DoesNotContain => "Doesn't contain(不包含)", FilterOperation.EndsWith => "Ends with(结尾为)", FilterOperation.Equals => "Equals(等于)", FilterOperation.DoesNotEqual => "Doesn't equal(不等于)", _ => "" } </ItemTemplate> </DxComboBox> <DxTextBox @bind-Value="@_brandSecondaryCodeFilterValue" Input="@(e => ApplyColumnFilter("brand_secondary_code", _brandSecondaryCodeFilterOp, _brandSecondaryCodeFilterValue))" CssClass="flex-grow-1"/> </div> </FilterRowCellTemplate> </DxGridDataColumn> </Columns> <ToolbarTemplate> <DxToolbar> <DxToolbarItem Text="Export to XLSX" Click="ExportXlsx_Click" /> <DxToolbarItem Text="Export to XLS" Click="ExportXls_Click" /> <DxToolbarItem Text="Export to CSV" Click="ExportCsv_Click" /> </DxToolbar> </ToolbarTemplate> </DxGrid> @code { IEnumerable<object> Data { get; set; } IGrid Grid { get; set; } public Brands.Root BrandsData { get; set; } = new Brands.Root(); public enum FilterOperation { BeginsWith, Contains, DoesNotContain, EndsWith, Equals, DoesNotEqual } private FilterOperation _brandCodeFilterOp = FilterOperation.Contains; private string _brandCodeFilterValue = string.Empty; private FilterOperation _brandNameFilterOp = FilterOperation.Contains; private string _brandNameFilterValue = string.Empty; private FilterOperation _brandSecondaryCodeFilterOp = FilterOperation.Contains; private string _brandSecondaryCodeFilterValue = string.Empty; protected override async Task OnInitializedAsync() { using var client = new HttpClient(); var apiUrlWithToken = $"{GlobalVariables.ApiUrl}?token={GlobalVariables.Token}"; var result = await client.GetStringAsync(apiUrlWithToken); BrandsData = JsonConvert.DeserializeObject<Brands.Root>(result); StateHasChanged(); } async Task ExportXlsx_Click() { await Grid.ExportToXlsxAsync("ExportResult"); } async Task ExportXls_Click() { await Grid.ExportToXlsAsync("ExportResult"); } async Task ExportCsv_Click() { await Grid.ExportToCsvAsync("ExportResult"); } private void ApplyColumnFilter(string fieldName, FilterOperation op, string value) { if (string.IsNullOrWhiteSpace(value)) { Grid.ClearColumnFilter(fieldName); return; } var criteria = op switch { FilterOperation.BeginsWith => CriteriaOperator.Parse($"{fieldName} Like ?", $"{value}%"), FilterOperation.Contains => CriteriaOperator.Parse($"{fieldName} Like ?", $"%{value}%"), FilterOperation.DoesNotContain => CriteriaOperator.Parse($"Not ({fieldName} Like ?)", $"%{value}%"), FilterOperation.EndsWith => CriteriaOperator.Parse($"{fieldName} Like ?", $"%{value}"), FilterOperation.Equals => CriteriaOperator.Parse($"{fieldName} = ?", value), FilterOperation.DoesNotEqual => CriteriaOperator.Parse($"{fieldName} != ?", value), _ => null }; if (criteria != null) { Grid.SetColumnFilter(fieldName, criteria); } } }
内容的提问来源于stack exchange,提问作者Nicholas Grammatopoulos
相关产品推荐
相关产品推荐

