New to Telerik UI for ASP.NET CoreStart a free 30-day trial

Implementing a Dynamic Grid

Environment

ProductTelerik UI for ASP.NET Core Grid

Description

How can I create Telerik UI for ASP.NET Core Grid that has dynamic columns?

Solution

This article describes the following use-case scenarios:

Basic Dynamic Binding

The following example demonstrates how to create a dynamic Grid that binds to a DataTable.

Razor
    @model System.Data.DataTable

    @(Html.Kendo().Grid<dynamic>()
        .Name("Grid")
        .Columns(columns =>
        {
            foreach (System.Data.DataColumn column in Model.Columns)
            {
                var c = columns.Bound(column.ColumnName);
            }
        })
        .Scrollable()
        .Height(400)
        .Pageable()
        .Sortable()
        .Filterable()
        .DataSource(dataSource => dataSource
            .Ajax()
            .PageSize(20)
            .Model(model =>
            {
                foreach (System.Data.DataColumn column in Model.Columns)
                {
                    var field = model.Field(column.ColumnName, column.DataType);
                }
            })
            .Read(read => read.Action("Customers_Read", "Grid"))
        )
    )

To review the complete example, refer to the ASP.NET Core application in the UI for ASP.NET Core Examples repository.

Dynamic Column Titles

The System.Data.DataColumn has a Caption property that can be used to dynamically change the title of the columns:

Razor
.Columns(columns =>
{
    foreach (System.Data.DataColumn column in Model.Columns)
    {
        var c = columns.Bound(column.ColumnName).Title(column.Caption);
    }
})

Dynamic Editing

Since dynamic editing is not part of the official built-in options, which utilized strongly typed models for ASP.NET Core, there are different solutions that can be applied.

  1. First, add the model Id() option—the primary key of the table. Also, use the Editable() option to specify the non-editable fields.

    Razor
    .Model(model =>
    {
        var id = Model.PrimaryKey[0].ColumnName;
        model.Id(id);
        foreach (System.Data.DataColumn column in Model.Columns)
        {
            var field = model.Field(column.ColumnName, column.DataType);
            if (column.ColumnName == id) {
                field.Editable(false);
            }
    
        }
    })
  2. Use IFormCollection to intercept the updated data item on the server.

    C#
        public JsonResult Customers_Update([DataSourceRequest] DataSourceRequest request, IFormCollection data)
        {
            ... // Update Action logic.
        }
  3. Alternatively, you can post the Model and values to the server in the desired format, so that you can process them and update the corresponding table accordingly.

    Razor
    @(Html.Kendo().Grid<dynamic>()
        .Name("gridMetadata")
        .Events(events => events.Save("savePopUpChange")) // Handle the "Save" event of the Grid.
        .Editable(ed=>ed.Mode(GridEditMode.PopUp)) 
        ... // Additional configuration.
        .DataSource(dataSource => dataSource
            .Ajax()
            ... // Additional configuration.
            .Update(update => update.Action("Metadata_Update", "Grid").Data("updateValuesData")) // Send additional data through the Update request.
        )
    )
  4. To define the column editors based on a condition, you can use a switch case:

    Razor
    @model System.Data.DataTable
    
    @(Html.Kendo().Grid<dynamic>()
        .Name("gridMetadata")
        .Columns(columns =>
        {
            foreach (System.Data.DataColumn dcolumn in Model.Columns)
            {
                switch (dcolumn.DataType.ToString())
                {
                    case "System.Int16":
                    case "System.Int32":
                    case "System.Int64":
                        columns.Bound(dcolumn.ColumnName).Title(dcolumn.Caption).EditorTemplateName("Integer");                                 
                        break;
    
                    case "System.Decimal":
                    case "System.Double":
                    case "System.Float":
                        columns.Bound(dcolumn.ColumnName).Title(dcolumn.Caption).EditorTemplateName("Number");
                        break;
                    case "System.String":
                        columns.Bound(dcolumn.ColumnName).Title(dcolumn.Caption).EditorTemplateName("String");                                 
                        break;
                    case "System.Byte":
                    case "System.Boolean":
                        columns.Bound(dcolumn.ColumnName).Title(dcolumn.Caption).EditorTemplateName("Boolean");                                 
                        break;
                    case "System.DateTime":
                        columns.Bound(dcolumn.ColumnName).Title(dcolumn.Caption).Format("{0:d}").EditorTemplateName("Date");
                        break;
                    default:
                        columns.Bound(dcolumn.ColumnName).Title(dcolumn.Caption).EditorTemplateName("String");                               
                        break;
                }
            }
            columns.Command(command =>  {command.Edit();});
        })
        ... // Additional configuration.
    )

For runnable examples of a dynamic Grid with editing, refer to the following example applications in GitHub:

Dynamic Grid In Razor Pages

The following example shows how to create a dynamic Grid in a Razor Pages scenario.

Razor
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@Html.AntiForgeryToken()

<script>
    function sendTokens() {
        return kendo.antiForgeryTokens();
    }
</script>

@(Html.Kendo().Grid<dynamic>()
    .Name("Grid")
    .Columns(columns =>
    {
        foreach (System.Data.DataColumn column in Model.DataTable.Columns)
        {
            var c = columns.Bound(column.ColumnName);
        }
    })
    .DataSource(dataSource => dataSource
        .Ajax()
        .Model(model =>
        {
            foreach (System.Data.DataColumn column in Model.DataTable.Columns)
            {
                var field = model.Field(column.ColumnName, column.DataType);
            }
        })
        .Read(r => r.Url(Url.Page("Index", "Read")).Data("sendTokens"))
    )
)

More ASP.NET Core Grid Resources

See Also