I am trying to develop a custom PropertyColumn on MudBlazor that has a custom filter based on checkbox. The problem I am facing is that the UI of the FilterTemplate is not reacting to events: for example if I click on the checkbox Select All, the others checkboxes are not updated.
@using System.Linq.Expressions;
@typeparam T
@typeparam TProperty
<PropertyColumn Property="Property" Title="@Title" HeaderStyle="@HeaderStyle" CellStyle="@CellStyle" @ref="_refCol">
<FilterTemplate>
<MudStack Spacing="0">
<MudCheckBox T="bool" Label="Select All" Size="@Size.Small" Checked="@_selectAll" CheckedChanged="SelectAll" />
<MudStack Spacing="0" Style="overflow-y:auto;max-height:250px">
@foreach (var item in _allDistinctValues)
{
<MudCheckBox T="bool" Label="@(item.ToString())" Size="@Size.Small" Checked="@(_valuesSelected.Contains(item))"
CheckedChanged="@((value) => SelectedChanged(value, item))" />
}
</MudStack>
<MudStack Row="true">
<MudButton OnClick="@(() => ClearFilterAsync(context))">Clear</MudButton>
<MudButton Color="@Color.Primary" OnClick="@(() => ApplyFilterAsync(context))">Filter</MudButton>
</MudStack>
</MudStack>
</FilterTemplate>
</PropertyColumn>
@code {
[Parameter]
public Expression<Func<T, TProperty>> Property { get; set; } = Expression.Lambda<Func<T, TProperty>>(Expression.Default(typeof(TProperty)), Expression.Parameter(typeof(T)));
[Parameter]
public string Title { get; set; }
[Parameter]
public string HeaderStyle { get; set; }
[Parameter]
public string CellStyle { get; set; }
PropertyColumn<T, TProperty> _refCol;
HashSet<TProperty> _allDistinctValues = new();
HashSet<TProperty> _valuesSelected = new();
HashSet<TProperty> _valuesFilter = new();
FilterDefinition<T> _filterDefinition;
bool _selectAll = true;
private void SelectedChanged(bool value, TProperty item)
{
if (value)
{
_valuesSelected.Add(item);
}
else
_valuesSelected.Remove(item);
if (_valuesSelected.Count == _allDistinctValues.Count)
{
_selectAll = true;
}
else
{
_selectAll = false;
}
}
private void SelectAll(bool value)
{
_selectAll = value;
if (value)
{
_valuesSelected = _allDistinctValues.ToHashSet();
}
else
{
_valuesSelected.Clear();
}
}
private async Task ClearFilterAsync(FilterContext<T> context)
{
_valuesSelected = _allDistinctValues.ToHashSet();
_valuesFilter = _allDistinctValues.ToHashSet();
_selectAll = true;
if (_filterDefinition != null)
foreach (var filter in context.FilterDefinitions.Where(f => f.Column.PropertyName == _filterDefinition.Column.PropertyName).ToList())
await context.Actions.ClearFilterAsync(filter);
}
private async Task ApplyFilterAsync(FilterContext<T> context)
{
_valuesFilter = _valuesSelected.ToHashSet();
if (_filterDefinition == null)
{
_filterDefinition = new FilterDefinition<T>
{
FilterFunction = x => _valuesFilter.Contains(Property.Compile().Invoke(x)),
Column = _refCol,
Operator = "dummy",
Value = "dummy"
};
}
await context.Actions.ApplyFilterAsync(_filterDefinition);
}
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
_allDistinctValues = _refCol.DataGrid.Items.Select(x => Property.Compile().Invoke(x)).Distinct().ToHashSet();
_valuesSelected = _allDistinctValues.ToHashSet();
_valuesFilter = _allDistinctValues.ToHashSet();
}
base.OnAfterRender(firstRender);
}
}
Below is the snippet of how I would use this property column inside a datagrid
<CustomPropertyColumn Property="x => x.PointName" Title="Point" HeaderStyle="width: 13%;" CellStyle="width: 13%;"></CustomPropertyColumn>