Filtering issue with RadzenGrid

I have an issue with my radzendatagrid component. When I apply a filter I get an error and I'm not sure how to continue debugging this.

The first error I got is regarding Virtualization:

fail: Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost[111]
      Unhandled exception in circuit 's0xlwEhWHz8NIQoJxTv-9LSKv3OWdfh8X9Hmqx_edNk'.
      System.IndexOutOfRangeException: Index was outside the bounds of the array.
         at Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize`1.BuildRenderTree(RenderTreeBuilder builder)

I thought that maybe filtering doesn't work when Virtualization is enabled so I tried to disable it dynamically when filtering is enabled

However now I get this error:

fail: Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost[111]
      Unhandled exception in circuit '2SpoCEThy91ieob7OsqCsL4fXcLATK6Mj_-TLovuLT8'.
      System.IndexOutOfRangeException: Index was outside the bounds of the array.
         at Radzen.QueryableExtension.GetNestedPropertyExpression(Expression expression, String property, Type type)
         at Radzen.QueryableExtension.GetExpression[T](ParameterExpression parameter, FilterDescriptor filter, FilterCaseSensitivity filterCaseSensitivity, Type type)
         at Radzen.QueryableExtension.Where[T](IQueryable1 source, IEnumerable1 filters, LogicalFilterOperator logicalFilterOperator, FilterCaseSensitivity filterCaseSensitivity)
         at Radzen.QueryableExtension.Where[T](IQueryable1 source, IEnumerable1 columns)
         at Radzen.Blazor.RadzenDataGrid1.get_View()
         at Radzen.PagedDataBoundComponent1.get_PagedView()
         at Radzen.Blazor.RadzenDataGrid1.DrawGroupOrDataRows(RenderTreeBuilder builder, IList1 visibleColumns)
         at Radzen.Blazor.RadzenDataGrid1.<>c__DisplayClass22_0.<DrawRows>b__0(RenderTreeBuilder builder)
         at Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder.AddContent(Int32 sequence, RenderFragment fragment)
         at Radzen.Blazor.RadzenDataGrid1.<BuildRenderTree>b680_0(RenderTreeBuilder builder2)
         at Microsoft.AspNetCore.Components.CascadingValue`1.Render(RenderTreeBuilder builder)
         at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, Exception& renderFragmentException)

This is my code:

        <RadzenDataGrid
            @ref="_grid"
            ID="@($"grid_{Control.Id}")"
            Data="SafeData"
            @bind-Value=@Control.SelectedItems
            @bind-Settings="@Control.Settings"
            LoadSettings="@LoadSettings"
            TItem="IDictionary<string, object>"
            class="@HiddenCaption"
            Style="@style"
            AllowFiltering="@Control.ShowFilters"
            AllowColumnResize="true"
            EmptyText=""
            FilterPopupRenderMode="PopupRenderMode.OnDemand"
            FilterMode="FilterMode.Advanced"
            FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive"
            LogicalFilterOperator="LogicalFilterOperator.Or"
            SelectionMode="@Control.RowSelection"
            AllowPaging="@Control.AllowPaging"
            AllowVirtualization="@(!Control.ShowFilters)"
            AllowSorting="@Control.AllowSort"
            CellRender="_OnCellRender"
            ColRender="_OnColRender"
            CellClick="@_OnCellClick"
            RowClick="_OnRowClick"
            RowDoubleClick="_OnRowDoubleClick"
            CellContextMenu="@_OnCellContextMenu">

            <HeaderTemplate>
                <RadzenLabel TextAlign="TextAlign.Center" Text="@Control.Caption"></RadzenLabel>
            </HeaderTemplate>

            <Columns>
                @foreach (var column in @Control.Columns)
                {
                    <RadzenDataGridColumn
                        Width="@CololumWidth(column.Value.Width)"
                        Frozen="@column.Value.Frozen"
                        Visible="@column.Value.Visible"
                        @key=@column.Key
                        Title="@column.Value.Title"
                        Type="column.Value.TItem"
                        TextAlign="@column.Value.TextAlign"
                        FormatString="@column.Value.FormatString"
                        Property="@column.Key">
                        <Template>
                            @if (Control.AllowEdit && !(column.Value.Locked ?? false))
                            {
                                <FreematicaEditGridCellTemplate Column="column" Row="context" Control="Control"></FreematicaEditGridCellTemplate>
                            }
                            else
                            {
                                <FreematicaGridCellTemplate Column="column" Row="context" Control="Control"></FreematicaGridCellTemplate>
                            }
                        </Template>
                    </RadzenDataGridColumn>
                }

            </Columns>

        </RadzenDataGrid>

Any help would be greatly appreciated. I'm using Radzen 6. This same component worked on Radzen 4 but I cannot tell for certain if it broke because of the version change or something else.

To provide any additional details we will need runnable code where we can reproduce the problem.

It was an issue with the property column name. Issue closed

I thought I fixed it changing the Property name but I was wrong. Here's a reproducible example:

Main razor file:

@page "/radzen-grid-sample"
@using System.Collections.Generic
@using System.Linq
@using FilterOperator = Radzen.FilterOperator

<RadzenDataGrid AllowPaging="true" AllowSorting="true" AllowFiltering="true" Data="@_orders"
                FilterMode="FilterMode.Simple"
                TItem="IDictionary<string, object>">
    <Columns>
        <RadzenDataGridColumn Property="CompanyName" Title="Company Name">
            <Template>
                @context["CompanyName"]
            </Template>
        </RadzenDataGridColumn>
        <RadzenDataGridColumn Property="ProductNames" Title="Product Name" Sortable="false">
            <Template>
                @context["ProductNames"]
            </Template>
        </RadzenDataGridColumn>
    </Columns>
</RadzenDataGrid>

@code {
    IEnumerable<IDictionary<string, object>> _orders = null!;

    protected override void OnInitialized()
    {
        // Create mock data first using the original models
        var mockOrders = CreateMockData();

        // Then convert the mock data to a list of dictionaries
        _orders = mockOrders.Select(order =>
        {
            var dictionary = new Dictionary<string, object>
            {
                ["OrderID"] = order.OrderID,
                ["CustomerID"] = order.CustomerID,
                ["OrderDate"] = order.OrderDate,
                ["CompanyName"] = order.Customer.CompanyName,
                ["ProductNames"] = string.Join(", ", order.OrderDetails.Select(od => od.Product.ProductName))
            };
            return dictionary;
        }).ToList();
    }

}

The .razor.cs file which I use to populate mock data:

using Microsoft.AspNetCore.Components;

namespace Satellite.Components.Pages.Testing;

public partial class TestingGrid : ComponentBase
{
    // Define the models for creating mock data
    public class Customer
    {
        public string CustomerID { get; set; }
        public string CompanyName { get; set; }
    }

    public class Product
    {
        public int ProductID { get; set; }
        public string ProductName { get; set; }
    }

    public class OrderDetail
    {
        public int OrderDetailID { get; set; }
        public int OrderID { get; set; }
        public int ProductID { get; set; }
        public Product Product { get; set; }
        public decimal Quantity { get; set; }
    }

    public class Order
    {
        public int OrderID { get; set; }
        public string CustomerID { get; set; }
        public DateTime OrderDate { get; set; }
        public Customer Customer { get; set; }
        public List<OrderDetail> OrderDetails { get; set; } = new List<OrderDetail>();
    }

    private static List<Order> CreateMockData()
    {
        // Create mock customers
        var customers = new List<Customer>
        {
            new() { CustomerID = "ALFKI", CompanyName = "Alfreds Futterkiste" },
            new() { CustomerID = "ANATR", CompanyName = "Ana Trujillo Emparedados y helados" },
            new() { CustomerID = "ANTON", CompanyName = "Antonio Moreno Taquería" },
            new() { CustomerID = "AROUT", CompanyName = "Around the Horn" },
            new() { CustomerID = "BERGS", CompanyName = "Berglunds snabbköp" }
        };

        // Create mock products
        var products = new List<Product>
        {
            new() { ProductID = 1, ProductName = "Chai" },
            new() { ProductID = 2, ProductName = "Chang" },
            new() { ProductID = 3, ProductName = "Aniseed Syrup" },
            new() { ProductID = 4, ProductName = "Chef Anton's Cajun Seasoning" },
            new() { ProductID = 5, ProductName = "Tofu" },
            new() { ProductID = 6, ProductName = "Konbu" },
            new() { ProductID = 7, ProductName = "Alice Mutton" },
            new() { ProductID = 8, ProductName = "Carnarvon Tigers" }
        };

        // Create mock orders with order details
        var orders = new List<Order>();
        var rand = new Random(123);

        for (var i = 1; i <= 50; i++)
        {
            var customer = customers[rand.Next(customers.Count)];
            var order = new Order
            {
                OrderID = i,
                CustomerID = customer.CustomerID,
                OrderDate = DateTime.Now.AddDays(-rand.Next(1, 365)),
                Customer = customer,
                OrderDetails = []
            };

            // Add 1-3 products to each order
            var numProducts = rand.Next(1, 4);
            for (var j = 0; j < numProducts; j++)
            {
                var product = products[rand.Next(products.Count)];
                order.OrderDetails.Add(new OrderDetail
                {
                    OrderDetailID = i * 10 + j,
                    OrderID = i,
                    ProductID = product.ProductID,
                    Product = product,
                    Quantity = rand.Next(1, 10)
                });
            }

            orders.Add(order);
        }

        // Ensure at least some orders have Tofu
        var tofuProduct = products.First(p => p.ProductName == "Tofu");
        for (var i = 0; i < 10; i++)
        {
            var order = orders[i];
            if (order.OrderDetails.All(od => od.Product.ProductName != "Tofu"))
            {
                order.OrderDetails.Add(new OrderDetail
                {
                    OrderDetailID = order.OrderID * 10 + 9,
                    OrderID = order.OrderID,
                    ProductID = tofuProduct.ProductID,
                    Product = tofuProduct,
                    Quantity = rand.Next(1, 10)
                });
            }
        }

        return orders;
    }
}

The error occurs when I try to filter by a column

I think I'm failing to understand the role of Property attribute and how it really works and relates to creating the grid and filtering

In the case of dynamic data (IDictionary<string,object>) you cannot simply specify it like this. Check this demo for reference:

1 Like

Thanks. I'll take a look I think this is just what I needed

I think the example is missing some code? I'm trying to see where PropertyAccess and GetDynamicPropertyExpression is defined but it does not seem to be on that code snippet

Oh I see it's internal of radzen. I can see the implementation on my IDE

Yes, this method is part of our library - it's not part of the example itself.

I managed to half make it work using the reference example you provided, thanks

I say half work because for some reason several columns still give me an error when filtering. It's a bit hard for me to provide an example right now so I was wondering if perhaphs the error log could make you think of a hint of what might be going on:

Here's error that I get in one column (seems something related with null values, I think when I populate the dictionary I'd need to convert from DBNull to or an empty string?)

      System.InvalidCastException: Unable to cast object of type 'System.DBNull' to type 'System.String'.

And here's another error I get on a different column, the property name this col gets is (String)it["Descripción Serv."] maybe the dot (.) makes it break somehow?

      System.ArgumentException: '"]' is not a member of type 'System.String' (Parameter 'propertyOrFieldName')
         at Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize`1.BuildRenderTree(RenderTreeBuilder builder)
         at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, Exception& renderFragmentException)

Use null instead DBNull for your data. Try to use also simple column names and add additional entry in the dictionary for Title if you need something more descriptive - dots are reserved for referencing sub properties in expressions usually.

1 Like

This worked thanks, issue closed