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;
// 其他过滤逻辑...
}
}
高级应用技巧
-
动态类型处理:对于混合类型数据,可以增加类型检测逻辑,自动选择合适的比较方式。
-
本地化支持:可以将过滤选项的文本内容提取为资源,支持多语言界面。
-
性能优化:对于大型数据集,可以考虑实现延迟过滤或分批次过滤。
-
组合条件:扩展当前实现,支持AND/OR逻辑组合多个过滤条件。
总结
通过本文介绍的方法,我们成功扩展了Blazorise DataGrid的过滤功能,使其支持更丰富的过滤操作,特别是针对数值型数据的比较操作。这种扩展方式展示了Blazorise框架的良好扩展性,开发者可以根据实际需求灵活定制组件功能。
虽然未来Blazorise可能会内置更强大的过滤功能,但掌握这种定制方法将使你能够应对各种特殊需求场景,提升开发效率和用户体验。