
En uno de mis proyectos recientes desarrollados con .NET 9 y MudBlazor, me encontré con la necesidad de mejorar los filtros que ofrece MudDataGrid. Si bien el componente ya trae una base sólida, para columnas booleanas quería algo más práctico y visual, algo similar a lo que vemos en sistemas administrativos profesionales.
Por eso construí un componente personalizado llamado BooleanFilterColumn, que me permite seleccionar rápidamente entre Todos, Activo o Inactivo, usando un pequeño popover con checkboxes.
En este artículo te cuento por qué lo hice, cómo funciona y cómo puedes utilizarlo tú también.
¿Por qué crear un filtro booleano personalizado?
MudBlazor permite aplicar filtros personalizados, pero para las columnas booleanas normalmente solo tenemos opciones binarias o expresiones. Yo quería algo más intuitivo:
- Un botón de filtro con el icono que cambia según si hay filtros aplicados.
- Un popover con checkboxes para seleccionar:
- Todos
- Activos
- Inactivos
- Aplicar o limpiar el filtro con un solo clic.
- Soporte para personalizar textos (por ejemplo: “Activo”, “Inactivo”, “Todos”, etc.)
El resultado fue este componente Razor:
@typeparam T
<MudIconButton OnClick="@(() => _open = true)" Icon="@_icon" Size="Size.Small" />
<MudOverlay Visible="@_open" OnClick="@(() => _open = false)" />
<MudPopover Open="@_open" AnchorOrigin="Origin.BottomCenter" TransformOrigin="Origin.TopCenter" Class="px-4 py-2">
<MudStack Spacing="0">
<MudCheckBox T="bool" Label="@AllText" Size="Size.Small"
Value="@_selectAll"
ValueChanged="@SelectAllChanged" />
<MudStack Spacing="0">
<MudCheckBox T="bool" Label="@TrueText"
Value="@_selectedValues.Contains(true)"
ValueChanged="@(v => ValueChanged(v, true))"
Size="Size.Small" />
<MudCheckBox T="bool" Label="@FalseText"
Value="@_selectedValues.Contains(false)"
ValueChanged="@(v => ValueChanged(v, false))"
Size="Size.Small" />
</MudStack>
<MudStack Row="true">
<MudButton OnClick="Clear">@ClearButtonText</MudButton>
<MudSpacer/>
<MudButton Color="Color.Primary" OnClick="Apply">@ApplyButtonText</MudButton>
</MudStack>
</MudStack>
</MudPopover>
@code {
[Parameter] public IEnumerable<T> Items { get; set; } = Enumerable.Empty<T>();
[Parameter] public Func<T, bool?> ValueSelector { get; set; } = default!;
[Parameter] public FilterContext<T> Context { get; set; } = default!;
[Parameter] public string ApplyButtonText { get; set; } = "Apply";
[Parameter] public string AllText { get; set; } = "All";
[Parameter] public string ClearButtonText { get; set; } = "Clear";
[Parameter] public string TrueText { get; set; } = "True";
[Parameter] public string FalseText { get; set; } = "False";
private bool _open;
private bool _selectAll = true;
private string _icon = Icons.Material.Outlined.FilterAlt;
private HashSet<bool> _selectedValues = new();
private FilterDefinition<T>? _filterDefinition;
protected override void OnParametersSet()
{
if (_selectAll)
_selectedValues = new HashSet<bool> { true, false };
_filterDefinition ??= new FilterDefinition<T>
{
FilterFunction = x =>
{
var val = ValueSelector(x);
return val is not null && _selectedValues.Contains(val.Value);
}
};
}
private void SelectAllChanged(bool value)
{
_selectAll = value;
if (value)
_selectedValues = new HashSet<bool> { true, false };
else
_selectedValues.Clear();
}
private void ValueChanged(bool value, bool val)
{
if (value)
_selectedValues.Add(val);
else
_selectedValues.Remove(val);
_selectAll = _selectedValues.Count == 2;
}
private async Task Clear()
{
_selectedValues.Clear();
_selectAll = false;
_icon = Icons.Material.Outlined.FilterAlt;
if (_filterDefinition is not null)
await Context.Actions.ClearFilterAsync(_filterDefinition);
_open = false;
}
private async Task Apply()
{
_icon = _selectedValues.Count == 2
? Icons.Material.Outlined.FilterAlt
: Icons.Material.Filled.FilterAlt;
if (_filterDefinition is not null)
await Context.Actions.ApplyFilterAsync(_filterDefinition);
_open = false;
}
}¿Cómo funciona internamente?
- Recibe una lista de items (
Items) provenientes del contexto de filtrado de MudDataGrid. - Extrae los valores booleanos distintos (
true/false) utilizandoValueSelector. - Muestra tres opciones:
- Todos
- TrueText
- FalseText
- Actualiza el ícono dependiendo del estado del filtro.
- Construye un
FilterDefinition<T>personalizado y lo aplica usando:
await Context.Actions.ApplyFilterAsync(_filterDefinition);Además, todo vive dentro de un MudPopover, usando MudCheckBox para representar las opciones.
Ejemplo de uso: BooleanFilterColumn
Así es como lo estoy usando actualmente en una columna booleana (por ejemplo, “Activo”)
<PropertyColumn Property="x => x.Activo" Title="Activo">
<CellTemplate>
<MudCheckBox Value="@context.Item.Activo" ReadOnly="true"/>
</CellTemplate>
<FilterTemplate>
<BooleanFilterColumn T="Rubro"
Items="context.Items"
ValueSelector="x => x.Activo"
Context="context"
AllText="Todos"
ApplyButtonText="Aplicar"
ClearButtonText="Limpiar"
TrueText="ACTIVO"
FalseText="INACTIVO" />
</FilterTemplate>
</PropertyColumn>Con eso, el usuario tiene un filtro booleano más claro y fácil de usar.
Conclusión
Este filtro ha sido un gran agregado a mi MudDataGrid, haciéndolo más amigable y funcional para columnas booleanas. Si también estás creando aplicaciones administrativas con MudBlazor, probablemente te sea muy útil tener un filtro tan visual y práctico.
Deja un comentario