v.6.0.x of Radzen Blazor breaks DataGrid custom filter functionality #1632

Closed
opened 2026-01-29 17:56:31 +00:00 by claunia · 8 comments
Owner

Originally created by @StephenJabs on GitHub (Feb 20, 2025).

Describe the bug
Upgraded NuGet package for Radzen.Blazor to v.6.0.x
Custom filter functionality no longer works (the items do not filter).

Downgraded to v.5.9.9
Custom filter functionality works again.

To Reproduce

  • Create a RadzenDataGridColumn with FilterOperator set to Custom
  • Create a FilterTemplate and connect events to buttons
  • Create a whereExpression to filter values
  • Call async column.SetCustomFilterExpressionAsync(whereExpression);
<RadzenDataGridColumn TItem="PhonelistData" FilterOperator="FilterOperator.Custom" LogicalFilterOperator="LogicalFilterOperator.Or" Property="StudioEnum" Title="Studio" Width="80px">
    <FilterTemplate Context="column">
        <div class="rz-grid-filter">
            <span class="rz-grid-filter-label">Filter</span>
            <RadzenListBox @bind-Value="selectedStudios" Data="@studios" TextProperty="DisplayName" ValueProperty="Studio" AllowClear="true" Multiple="true" Style="width:220px; height:230px;" />
            <div class="rz-grid-filter-buttons" style="padding-top:10px; padding-bottom:0px;">
                <RadzenButton ButtonStyle="ButtonStyle.Base" Variant="Variant.Text" Style="background-color: unset !important;" Text="Clear" Click="@(() => OnStudioFilterClear(column))" />
                <RadzenButton ButtonStyle="ButtonStyle.Primary" Variant="Variant.Text" Text="Apply" Click="@(() => @OnStudioFilter(column))" />
            </div>
        </div>
    </FilterTemplate>
</RadzenDataGridColumn>
    protected async Task OnStudioFilter(RadzenDataGridColumn<PhonelistData> column)
    {
        string? whereExpression;
        if (selectedStudios?.Any() == true)
        {
            int filterValue = selectedStudios.Select(e => (int)e).Aggregate((current, next) => current | next);
            whereExpression = $"StudioEnum != null && (StudioEnum & {filterValue}) != 0";
        }
        else
        {
            whereExpression = null;
            selectedStudios = null;
        }
        await column.SetCustomFilterExpressionAsync(whereExpression);
        await column.CloseFilter();
    }

Desktop (please complete the following information):

  • OS: Windows 10 x64
  • Browser: Edge
  • Version: 133.0.3065.69 (latest)
Originally created by @StephenJabs on GitHub (Feb 20, 2025). **Describe the bug** Upgraded NuGet package for Radzen.Blazor to v.6.0.x Custom filter functionality no longer works (the items do not filter). Downgraded to v.5.9.9 Custom filter functionality works again. **To Reproduce** - Create a `RadzenDataGridColumn` with `FilterOperator` set to `Custom` - Create a `FilterTemplate` and connect events to buttons - Create a `whereExpression` to filter values - Call `async column.SetCustomFilterExpressionAsync(whereExpression);` ``` <RadzenDataGridColumn TItem="PhonelistData" FilterOperator="FilterOperator.Custom" LogicalFilterOperator="LogicalFilterOperator.Or" Property="StudioEnum" Title="Studio" Width="80px"> <FilterTemplate Context="column"> <div class="rz-grid-filter"> <span class="rz-grid-filter-label">Filter</span> <RadzenListBox @bind-Value="selectedStudios" Data="@studios" TextProperty="DisplayName" ValueProperty="Studio" AllowClear="true" Multiple="true" Style="width:220px; height:230px;" /> <div class="rz-grid-filter-buttons" style="padding-top:10px; padding-bottom:0px;"> <RadzenButton ButtonStyle="ButtonStyle.Base" Variant="Variant.Text" Style="background-color: unset !important;" Text="Clear" Click="@(() => OnStudioFilterClear(column))" /> <RadzenButton ButtonStyle="ButtonStyle.Primary" Variant="Variant.Text" Text="Apply" Click="@(() => @OnStudioFilter(column))" /> </div> </div> </FilterTemplate> </RadzenDataGridColumn> ``` ``` protected async Task OnStudioFilter(RadzenDataGridColumn<PhonelistData> column) { string? whereExpression; if (selectedStudios?.Any() == true) { int filterValue = selectedStudios.Select(e => (int)e).Aggregate((current, next) => current | next); whereExpression = $"StudioEnum != null && (StudioEnum & {filterValue}) != 0"; } else { whereExpression = null; selectedStudios = null; } await column.SetCustomFilterExpressionAsync(whereExpression); await column.CloseFilter(); } ``` **Desktop (please complete the following information):** - OS: Windows 10 x64 - Browser: Edge - Version: 133.0.3065.69 (latest)
Author
Owner

@akorchev commented on GitHub (Feb 21, 2025):

Hi @StephenJabs,

Info about the breaking changes introduced with 6.x is available here: https://forum.radzen.com/t/just-released-our-new-major-version-of-radzen-blazor-6-0-0-without-reference-to-system-linq-dynamic-core-nuget-package/19748

There is probably an exception thrown somewhere. What is the error message?

@akorchev commented on GitHub (Feb 21, 2025): Hi @StephenJabs, Info about the breaking changes introduced with 6.x is available here: https://forum.radzen.com/t/just-released-our-new-major-version-of-radzen-blazor-6-0-0-without-reference-to-system-linq-dynamic-core-nuget-package/19748 There is probably an exception thrown somewhere. What is the error message?
Author
Owner

@enchev commented on GitHub (Feb 21, 2025):

There is a demo showing how the custom expression should be updated. You need item instance in front of all property names:

Image

@enchev commented on GitHub (Feb 21, 2025): There is a demo showing how the custom expression should be updated. You need item instance in front of all property names: ![Image](https://github.com/user-attachments/assets/f2463947-bb6f-498f-acd4-a180152001c5)
Author
Owner

@StephenJabs commented on GitHub (Apr 29, 2025):

Finally revisiting this issue. I want to upgrade to Radzen 6+ controls.

How does one do bitwise comparisons now?

protected async Task OnAvailabilityFilter()
{
    RadzenDataGridColumn<PhonelistData>? column = grid.ColumnsCollection.FirstOrDefault(e => e.Property == "Status");

    if (column != null)
    {
        string? whereExpression = null;
        if (selectedAvailabilities.Count > 0)
        {
            string filterValue = selectedAvailabilities.Select(e => (int)e).Aggregate((current, next) => current | next).ToString();
            whereExpression = $"it.Status != null and (it.Status & {filterValue}) != 0";
        }
        await column.SetCustomFilterExpressionAsync(whereExpression);
        await column.CloseFilter();
        filterCount += 1;
        isFiltered = (filterCount > 0);
    }
}

Throws this:

System.InvalidOperationException: Invalid predicate: it => it.Status != null && (it.Status & 1) != 0
 ---> System.NotSupportedException: Unsupported operator: &
@StephenJabs commented on GitHub (Apr 29, 2025): Finally revisiting this issue. I want to upgrade to Radzen 6+ controls. How does one do bitwise comparisons now? ``` protected async Task OnAvailabilityFilter() { RadzenDataGridColumn<PhonelistData>? column = grid.ColumnsCollection.FirstOrDefault(e => e.Property == "Status"); if (column != null) { string? whereExpression = null; if (selectedAvailabilities.Count > 0) { string filterValue = selectedAvailabilities.Select(e => (int)e).Aggregate((current, next) => current | next).ToString(); whereExpression = $"it.Status != null and (it.Status & {filterValue}) != 0"; } await column.SetCustomFilterExpressionAsync(whereExpression); await column.CloseFilter(); filterCount += 1; isFiltered = (filterCount > 0); } } ``` Throws this: ``` System.InvalidOperationException: Invalid predicate: it => it.Status != null && (it.Status & 1) != 0 ---> System.NotSupportedException: Unsupported operator: & ```
Author
Owner

@StephenJabs commented on GitHub (Apr 30, 2025):

Nevermind, I see that you are introducing new expression parsing with v.7. I'll wait to try it with the latest version.

@StephenJabs commented on GitHub (Apr 30, 2025): Nevermind, I see that you are introducing new expression parsing with v.7. I'll wait to try it with the latest version.
Author
Owner

@akorchev commented on GitHub (Apr 30, 2025):

The v7 branch doesn't support bitwise parsing too. We will consider it.

@akorchev commented on GitHub (Apr 30, 2025): The v7 branch doesn't support bitwise parsing too. We will consider it.
Author
Owner

@StephenJabs commented on GitHub (Apr 30, 2025):

Any advice on how to handle this scenario then?

What about allowing calls to a custom function:

public static class FilterHelpers
{
    public static bool HasBit(int? value, int flag)
    {
        return (value ?? 0 & flag) != 0;
    }
}

And then call it like this:

await grid.SetCustomFilterExpressionAsync("FilterHelpers.HasBit(Status, 4)");
@StephenJabs commented on GitHub (Apr 30, 2025): Any advice on how to handle this scenario then? What about allowing calls to a custom function: ``` public static class FilterHelpers { public static bool HasBit(int? value, int flag) { return (value ?? 0 & flag) != 0; } } ``` And then call it like this: ``` await grid.SetCustomFilterExpressionAsync("FilterHelpers.HasBit(Status, 4)"); ```
Author
Owner

@akorchev commented on GitHub (Apr 30, 2025):

Calling helper methods is also not support and won't be supported. We will probably add support for bit operations. For now you should stick to v5.x and check v7 once it ships.

@akorchev commented on GitHub (Apr 30, 2025): Calling helper methods is also not support and won't be supported. We will probably add support for bit operations. For now you should stick to v5.x and check v7 once it ships.
Author
Owner

@StephenJabs commented on GitHub (May 21, 2025):

Were you able to incorporate bit operations into v7?

After upgrading to Radzen.Blazor v7.0.6, the call to SetCustomFilterExpressionAsync no longer throws any errors, but also does not do anything:

private List<Enums.User.Availability> selectedAvailabilities = [];

protected async Task OnAvailabilityFilter(RadzenDataGridColumn<PhonelistData> column)
{
    string? whereExpression = FilterHelpers.GetWhereExpression("Status", selectedAvailabilities);
    await column.SetCustomFilterExpressionAsync(whereExpression);
    await column.CloseFilter();
}
public class FilterHelpers
{
        public static string? GetWhereExpression<T>(string field, List<T>? selectedValues) where T : Enum
        {
            if (selectedValues == null || selectedValues.Count == 0)
                return null;

            bool isFlagsEnum = typeof(T).IsDefined(typeof(FlagsAttribute), inherit: false);

            if (isFlagsEnum)
            {
                int filterValue = selectedValues
                    .Select(e => Convert.ToInt32(e))
                    .Aggregate((current, next) => current | next);

                return $"it.{field} != null and (it.{field} & {filterValue}) != 0";
            }
            else
            {
                string conditions = string.Join(" or ", selectedValues
                    .Distinct()
                    .Select(e => $"it.{field} == {Convert.ToInt32(e)}"));

                return $"it.{field} != null and ({conditions})";
            }
        }
}

Here is some example output from GetWhereExpression:

"it.Status != null and (it.Status & 1) != 0"

Do I have to resort to filtering the source data assigned to the datagrid? My preference would be to continue using SetCustomFilterExpressionAsync to keep the code simple.

Right now I'm using a combination of filter types, like this:

            <RadzenDataGridColumn TItem="PhonelistData" FilterOperator="FilterOperator.Contains" LogicalFilterOperator="LogicalFilterOperator.Or" Property="JobTitle" Title="Job Title" Width="160px" Visible="@(windowWidth > 1200)" />
            <RadzenDataGridColumn TItem="PhonelistData" Filterable="false" Property="Credentials" Title="Credentials" Width="180px" Groupable="false" Visible="@(windowWidth > 1400)" />
            <RadzenDataGridColumn TItem="PhonelistData" FilterOperator="FilterOperator.Custom" LogicalFilterOperator="LogicalFilterOperator.Or" Property="DepartmentEnum" Title="Department" Width="100px" Visible="@(windowWidth > 1600)">
                <FilterTemplate Context="column">
                    <div class="rz-grid-filter">
                        <span class="rz-grid-filter-label">Filter</span>
                        <RadzenListBox @bind-Value="selectedDepartments" Data="@departments" TextProperty="DisplayName" ValueProperty="Department" AllowClear="true" Multiple="true" Style="width:220px; height:230px;" />
                        <div class="rz-grid-filter-buttons" style="padding-top:10px; padding-bottom:0px;">
                            <RadzenButton ButtonStyle="ButtonStyle.Base" Variant="Variant.Text" Style="background-color: unset !important;" Text="Clear" Click="@(() => OnDepartmentFilterClear(column))" />
                            <RadzenButton ButtonStyle="ButtonStyle.Primary" Variant="Variant.Text" Text="Apply" Click="@(() => OnDepartmentFilter(column))" />
                        </div>
                    </div>
                </FilterTemplate>
            </RadzenDataGridColumn>

I don't want to wire up events and create custom filter logic for every filter option if I can help it.

@StephenJabs commented on GitHub (May 21, 2025): Were you able to incorporate bit operations into v7? After upgrading to Radzen.Blazor v7.0.6, the call to `SetCustomFilterExpressionAsync` no longer throws any errors, but also does not do anything: ``` private List<Enums.User.Availability> selectedAvailabilities = []; protected async Task OnAvailabilityFilter(RadzenDataGridColumn<PhonelistData> column) { string? whereExpression = FilterHelpers.GetWhereExpression("Status", selectedAvailabilities); await column.SetCustomFilterExpressionAsync(whereExpression); await column.CloseFilter(); } ``` ``` public class FilterHelpers { public static string? GetWhereExpression<T>(string field, List<T>? selectedValues) where T : Enum { if (selectedValues == null || selectedValues.Count == 0) return null; bool isFlagsEnum = typeof(T).IsDefined(typeof(FlagsAttribute), inherit: false); if (isFlagsEnum) { int filterValue = selectedValues .Select(e => Convert.ToInt32(e)) .Aggregate((current, next) => current | next); return $"it.{field} != null and (it.{field} & {filterValue}) != 0"; } else { string conditions = string.Join(" or ", selectedValues .Distinct() .Select(e => $"it.{field} == {Convert.ToInt32(e)}")); return $"it.{field} != null and ({conditions})"; } } } ``` Here is some example output from `GetWhereExpression`: ``` "it.Status != null and (it.Status & 1) != 0" ``` Do I have to resort to filtering the source data assigned to the datagrid? My preference would be to continue using `SetCustomFilterExpressionAsync` to keep the code simple. Right now I'm using a combination of filter types, like this: ``` <RadzenDataGridColumn TItem="PhonelistData" FilterOperator="FilterOperator.Contains" LogicalFilterOperator="LogicalFilterOperator.Or" Property="JobTitle" Title="Job Title" Width="160px" Visible="@(windowWidth > 1200)" /> <RadzenDataGridColumn TItem="PhonelistData" Filterable="false" Property="Credentials" Title="Credentials" Width="180px" Groupable="false" Visible="@(windowWidth > 1400)" /> <RadzenDataGridColumn TItem="PhonelistData" FilterOperator="FilterOperator.Custom" LogicalFilterOperator="LogicalFilterOperator.Or" Property="DepartmentEnum" Title="Department" Width="100px" Visible="@(windowWidth > 1600)"> <FilterTemplate Context="column"> <div class="rz-grid-filter"> <span class="rz-grid-filter-label">Filter</span> <RadzenListBox @bind-Value="selectedDepartments" Data="@departments" TextProperty="DisplayName" ValueProperty="Department" AllowClear="true" Multiple="true" Style="width:220px; height:230px;" /> <div class="rz-grid-filter-buttons" style="padding-top:10px; padding-bottom:0px;"> <RadzenButton ButtonStyle="ButtonStyle.Base" Variant="Variant.Text" Style="background-color: unset !important;" Text="Clear" Click="@(() => OnDepartmentFilterClear(column))" /> <RadzenButton ButtonStyle="ButtonStyle.Primary" Variant="Variant.Text" Text="Apply" Click="@(() => OnDepartmentFilter(column))" /> </div> </div> </FilterTemplate> </RadzenDataGridColumn> ``` I don't want to wire up events and create custom filter logic for every filter option if I can help it.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/radzen-blazor#1632