首页
/ Blazorise项目实战:增强DataGrid菜单过滤功能的完整指南

Blazorise项目实战:增强DataGrid菜单过滤功能的完整指南

2025-07-09 07:16:50作者:郦嵘贵Just

前言

在Blazorise 1.3版本中,DataGrid组件引入了全新的菜单过滤模式(Menu mode),为用户提供了按列预定义过滤的功能。虽然这一功能显著提升了数据过滤的灵活性,但在实际应用中仍存在一些局限性。本文将深入探讨如何扩展DataGrid的过滤功能,使其支持更丰富的过滤操作。

理解现有过滤功能的局限性

当前DataGridFilterMethod仅支持以下几种基本过滤方式:

  • Contains(包含)
  • StartsWith(以...开头)
  • EndsWith(以...结尾)
  • Equals(等于)
  • NotEquals(不等于)

对于数值型数据列,我们通常还需要"大于"和"小于"这样的比较操作,这正是我们需要扩展的地方。

扩展过滤功能实现方案

第一步:定义扩展的过滤枚举

我们首先创建一个更丰富的MyFilter枚举,增加数值比较操作:

public enum MyFilter
{
    Equals, 
    NotEquals, 
    Contains, 
    StartsWith, 
    EndsWith, 
    GreaterThan,  // 新增
    LessThan      // 新增
}

第二步:实现过滤状态管理器

为了管理各列的过滤状态,我们需要创建一个FilterTracker类:

public class FilterTracker<T>
{
    public List<ColumnFilter<T>> ColumnFilters { get; set; }

    // 清除指定列的过滤条件
    public void ClearColumnFilter(DataGridColumn<T> column)
    {
        ColumnFilters ??= new();
        var filter = ColumnFilters.FirstOrDefault(x => x.Column.Field == column.Field);
        if (filter != null) ColumnFilters.Remove(filter);
    }

    // 设置列的过滤类型
    public void SetColumnFilter(DataGridColumn<T> column, MyFilter filter)
    {
        ColumnFilters ??= new();
        var columnFilter = ColumnFilters.FirstOrDefault(x => x.Column.Field == column.Field);
        if (columnFilter == null)
        {
            ColumnFilters.Add(new ColumnFilter<T> { Column = column, SelectedFilter = filter });
        }
        else
        {
            columnFilter.SelectedFilter = filter;
        }
    }

    // 获取列的过滤值
    public MyFilter GetColumnFilterValue(string fieldName)
        => GetColumnFilter(fieldName)?.SelectedFilter ?? MyFilter.Contains;
}

第三步:自定义过滤菜单模板

利用Blazorise提供的FilterMenuTemplate,我们可以自定义过滤界面:

<FilterMenuTemplate>
    <Row>
        <Column ColumnSize="ColumnSize.Is4">
            <Select TValue="MyFilter" 
                   SelectedValue="@_filterTracker.GetColumnFilterValue(context.Column.Field)" 
                   SelectedValueChanged="e => _filterTracker.SetColumnFilter(context.Column, e)">
                <SelectItem Value="@MyFilter.Contains">包含</SelectItem>
                <SelectItem Value="@MyFilter.StartsWith">开头为</SelectItem>
                <!-- 其他过滤选项 -->
                @if (context.Column.ColumnType == DataGridColumnType.Numeric)
                {
                    <SelectItem Value="@MyFilter.GreaterThan">大于</SelectItem>
                    <SelectItem Value="@MyFilter.LessThan">小于</SelectItem>
                }
            </Select>
        </Column>
        <Column ColumnSize="ColumnSize.Is4">
            <TextEdit Text="@_filterTracker.GetColumnSearchValue(context.Column.Field)" 
                     TextChanged="@(newValue => _filterTracker.SetColumnSearchValue(context.Column, newValue))" />
        </Column>
        <Column ColumnSize="ColumnSize.Is4">
            <Button Clicked="context.Filter" Color="Color.Primary">
                <Icon Name="IconName.Filter" /> 过滤
            </Button>
            <Button Clicked="@(() => {
                _filterTracker.ClearColumnFilter(context.Column);
                context.ClearFilter.InvokeAsync();
            })" Color="Color.Light">
                <Icon Name="IconName.Clear" /> 清除
            </Button>
        </Column>
    </Row>
</FilterMenuTemplate>

第四步:实现自定义过滤逻辑

最后,我们需要实现自定义过滤逻辑:

private bool MyCustomFilter(FilterExample row)
{
    if (_filterTracker.ColumnFilters == null) return true;
    
    return _filterTracker.ColumnFilters.All(x => EvaluateColumnFilter(x, row));
}

private bool EvaluateColumnFilter(ColumnFilter<FilterExample> columnFilter, FilterExample row)
{
    var getter = DataGrid.Utils.FunctionCompiler.CreateValueGetter<FilterExample>(columnFilter.Column.Field);
    var value = getter(row)?.ToString();
    
    return CompareValues(value, columnFilter.SearchValue, columnFilter.SelectedFilter);
}

private bool CompareValues(string value, string compareTo, MyFilter method)
{
    if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(compareTo)) return false;

    switch (method)
    {
        case MyFilter.GreaterThan:
            if (double.TryParse(value, out var num1) && double.TryParse(compareTo, out var num2))
                return num1 > num2;
            return false;
            
        case MyFilter.LessThan:
            if (double.TryParse(value, out var num3) && double.TryParse(compareTo, out var num4))
                return num3 < num4;
            return false;
            
        // 其他过滤逻辑...
    }
}

高级应用技巧

  1. 动态类型处理:对于混合类型数据,可以增加类型检测逻辑,自动选择合适的比较方式。

  2. 本地化支持:可以将过滤选项的文本内容提取为资源,支持多语言界面。

  3. 性能优化:对于大型数据集,可以考虑实现延迟过滤或分批次过滤。

  4. 组合条件:扩展当前实现,支持AND/OR逻辑组合多个过滤条件。

总结

通过本文介绍的方法,我们成功扩展了Blazorise DataGrid的过滤功能,使其支持更丰富的过滤操作,特别是针对数值型数据的比较操作。这种扩展方式展示了Blazorise框架的良好扩展性,开发者可以根据实际需求灵活定制组件功能。

虽然未来Blazorise可能会内置更强大的过滤功能,但掌握这种定制方法将使你能够应对各种特殊需求场景,提升开发效率和用户体验。