Mudblazor FilterTemplate UI not updating after event

177 Views Asked by At

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>
0

There are 0 best solutions below