Sort and filter dynamically created columns using complex objects in RadzenDataGrid

Hi,

I would need to sort and filter dynamically created columns using complex objects in RadzenDataGrid. I successfully passed the object of "TargetResult" for "Target1" and Target2" columns. Now I need to sort and filter per the object property "TestResultType".

Tried to use:

  • "SortProperty" property in RadzenDataGridColumn
  • "Sort" property in RadzenDataGrid
    but without success. I don't know how to implement them properly for this case.

Can you please give me an implementation how to sort and filter in such a case?

@page "/"

<PageTitle>Radzen DataGrid</PageTitle>

<RadzenDataGrid @bind-Value=@selectedItems Data ="@data" TItem="IDictionary<string, object>" SelectionMode="DataGridSelectionMode.Single"
                AllowFiltering="true" FilterPopupRenderMode="PopupRenderMode.OnDemand" FilterMode="FilterMode.Advanced"
                AllowPaging="true" AllowSorting="true">
    <Columns>
        @foreach (var column in columns)
        {
            switch (column.Key)
            {
                case "Name":
                    <RadzenDataGridColumn @key=@column.Key Title="@column.Key" Type="column.Value" Property="@GetColumnPropertyExpression(column.Key, column.Value)">
                        <Template>
                            @context[@column.Key]
                        </Template>
                    </RadzenDataGridColumn>
                    break;
                default:
                    <RadzenDataGridColumn @key=@column.Key Title="@column.Key" Type="column.Value" Property="@GetColumnPropertyExpression(column.Key, column.Value)">
                        <Template>
                            @if (@context[column.Key] is TargetResult tr)
                            {
                                @tr.TestResultType
                            }
                        </Template>
                    </RadzenDataGridColumn>
                    break;
            }            
        }
    </Columns>
</RadzenDataGrid>

@code {
    IList<IDictionary<string, object>> selectedItems;

    public IEnumerable<IDictionary<string, object>> data { get; set; }

    public IDictionary<string, Type> columns { get; set; }

    public string GetColumnPropertyExpression(string name, Type type)
    {
        var expression = $@"it[""{name}""].ToString()";

        if (type == typeof(int))
        {
            return $"int.Parse({expression})";
        }
        else if (type == typeof(DateTime))
        {
            return $"DateTime.Parse({expression})";
        }
        else if (type.IsEnum)
        {
            return $@"Int32(Enum.Parse(it[""{name}""].GetType(), {expression}))";
        }

        return expression;
    }

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();

        var testResults = new List<TestResult>()
        {
            new TestResult() {
                Name = "Test1",
                Results = new List<TargetResult>()
                {
                    new TargetResult()
                    {
                        RunId = 1,
                        TargetName = "Target1",
                        TestResultType = TestResultTypes.Passed
                    },
                    new TargetResult()
                    {
                        RunId = 2,
                        TargetName = "Target2",
                        TestResultType = TestResultTypes.Passed
                    }
                }
            },
            new TestResult() {
                Name = "Test2",
                Results = new List<TargetResult>()
                {
                    new TargetResult()
                    {
                        RunId = 3,
                        TargetName = "Target1",
                        TestResultType = TestResultTypes.Failed
                    },
                    new TargetResult()
                    {
                        RunId = 4,
                        TargetName = "Target2",
                        TestResultType = TestResultTypes.Failed
                    }
                }
            }
        };

        var targets = new List<string>() { "Target1", "Target2" };

        columns = new Dictionary<string, Type>()
        {
            { "Name", typeof(string) },
        };

        foreach (var target in targets)
        {
            columns.Add(target, typeof(TargetResult));
        }

        data = Enumerable.Range(0, testResults.Count()).Select(i =>
        {
            var row = new Dictionary<string, object>();

            foreach (var column in columns)
            {
                switch (column.Key)
                {
                    case "Name":
                        row.Add(column.Key, testResults[i].Name);
                        break;
                    default:
                        row.Add(column.Key, testResults[i].Results.First(tr => tr.TargetName.Equals(column.Key)));
                        break;
                }
            }

            return row;
        });
    }

    class TestResult
    {
        public string Name { get; set; }
        public List<TargetResult> Results { get; set; }
    }

    class TargetResult
    {
        public int RunId { get; set; }
        public string TargetName { get; set; }
        public TestResultTypes TestResultType { get; set; }
    }

    enum TestResultTypes
    {
        None = 0,
        Passed = 1,
        Failed = 2
    }
}

You can extend GetColumnPropertyExpression similar to other types.

Can you please give me an implementation example of extended GetColumnPropertyExpression by TargetResult object? I miss a proper syntax :frowning:

else if (type == typeof(TargetResult))
{
    // Need to use TargetResult.TestResultType which is enum
    return $@"Int32(Enum.Parse(it[""{name}""].GetType(), {expression}))";
}

Have you tried to debug your case? There is already code that handles enum.

Need to take enum from the property of the object, i.e. TargetResult.TestResultType.

Something like that:

else if (type == typeof(TargetResult))
{
    return $@"TargetResult.TestResultType";
}

I’ll repeat what I’ve already posted. Use the debugger to debug your code and especially to check the type and value of expression parts.