Dynamic columns based on List in ViewModel

2 posts, 1 answers
  1. Micah
    Micah avatar
    6 posts
    Member since:
    Jul 2014

    Posted 15 Aug 2014 Link to this post

    Dynamic columns seem to be incredibly tricky within the MVC Grid wrappers. I'm trying to build a grid where the columns represent a user-selectable range of years. As such, I have no knowledge of how many will be present at build time.

    ViewModel:
    <code>
    public class Indicator
    {
        public Grid Grid { get; set; }
    }

    public class Grid
    {
        public List<string> Columns { get; set; }
        public List<GridRow> Rows { get; set; }
    }

    public class GridRow
    {
        public string Label { get; set; }
        public List<decimal> Values { get; set; }
        public List<GridRow> ChildRows { get; set; }
    }
    </code>

    Controller method:
    <code>
    public ActionResult Index()
    {
        Indicator i = new Indicator();
        i.Grid = new Grid();
        i.Grid.Columns = new List<string> { "2011", "2012", "2013", "2014", "2015" };
        i.Grid.Rows = new List<GridRow>
        {
            new GridRow { Label = "First", Values = new List<decimal> { 5M, 2M, 1M, 8M, 10M } },
            new GridRow { Label = "Second", Values = new List<decimal> { 2M, 2M, 4M, 8M, 9M } },
            new GridRow { Label = "Third", Values = new List<decimal> { 12M, 8M, 1M, 9M, 3M } }
        };
        return View(i);
    }
    </code>

    View:
    <code>
    @model MyProject.ViewModels.Indicator

    @(Html.Kendo().Grid(Model.Grid.Rows)
        .Name("testGrid")
        .Columns(columns =>
        {
            columns.Bound(r => r.Label).Title("Type");
            int i = -1;
            foreach (var c in Model.Grid.Columns) {
                ++i;
                columns.Bound(r => r.Values.ElementAt(i)).Title(c);
            }
        })
    )
    </code>

    The problem is that r.Values.ElementAt(i) dies with: Bound columns require a field or property access expression. If I create a complex object in place of the list of decimals, I can then address a decimal field directly. However, this seems convoluted. Also, if I try to run .Format("{0}") at that point, 0 is the only element I can address and it points back to the first item in the List of complex objects, therefore printing that value across all columns.

    I'm having a hard time wrapping my head around how to get a dynamic number of columns into the Grid in a usable fashion.




  2. Answer
    Rosen
    Admin
    Rosen avatar
    3253 posts

    Posted 19 Aug 2014 Link to this post

    Hi Micah,

    In this case you will need to use Template instead of a Bound column. The tricky part will be to capture the state of the index within the Func used as the template:

    @model GridDynamicColumns.Models.Indicator
     
    @(Html.Kendo().Grid(Model.Grid.Rows)
        .Name("testGrid")
        .Columns(columns =>
        {
            columns.Bound(r => r.Label).Title("Type");
            for (int i = 0; i < Model.Grid.Columns.Count; i++)
            {
                var index = i;
                columns.Template(@<text>@item.Values[index].ToString("c")</text>).Title(Model.Grid.Columns[i]);
            }
            
        })


    Regards,
    Rosen
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
Back to Top