You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 16:55:56