Wednesday, February 6, 2013

AutoScaffold Index.cshtml tabular view site-wide

I was tired of generating the index.cshtml list over and over again everytime the model or viewmodel changes. So how could I get that to be runtime generated? Enter Haacked's article on Mvc Tabular Display Template Updated to work with Razor and with IEnumerable First the DisplayTemplate
@using System
@using MyMvc.Models
@model IEnumerable<dynamic>
@{
    //http://haacked.com/archive/2010/05/05/asp-net-mvc-tabular-display-template.aspx
    var items = Model.ToArray();
    var metadata = ModelMetadata.FromLambdaExpression(m => m.ToArray()[0], ViewData);
    var properties = metadata.Properties.Where(pm => TableViewHelper.ShouldShow(pm, ViewData)).OrderBy(pm => pm.Order);
}

<table>
    <thead>
        <tr>
            @foreach (var property in properties)
            {
                <th>@property.GetDisplayName()</th>
            }
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
            var itemMetadata = ModelMetadata.FromLambdaExpression(m => item, ViewData);
            <tr>
               
                @foreach (var property in properties)
                {
                    var propertyMetdata = itemMetadata.Properties.Single(m => m.PropertyName == property.PropertyName);
                    <td>
                        @Html.DisplayFor(m => propertyMetdata.Model)
                    </td>
                }
            </tr>
        }
    </tbody>
    
</table>

<span>Showing @Model.Count() items</span>
Then the helper
@using System
@using MyMvc.Models
@model IEnumerable<dynamic>
@{
    //http://haacked.com/archive/2010/05/05/asp-net-mvc-tabular-display-template.aspx
    var items = Model.ToArray();
    var metadata = ModelMetadata.FromLambdaExpression(m => m.ToArray()[0], ViewData);
    var properties = metadata.Properties.Where(pm => TableViewHelper.ShouldShow(pm, ViewData)).OrderBy(pm => pm.Order);
}

<table>
    <thead>
        <tr>
            @foreach (var property in properties)
            {
                <th>@property.GetDisplayName()</th>
            }
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
            var itemMetadata = ModelMetadata.FromLambdaExpression(m => item, ViewData);
            <tr>
               
                @foreach (var property in properties)
                {
                    var propertyMetdata = itemMetadata.Properties.Single(m => m.PropertyName == property.PropertyName);
                    <td>
                        @Html.DisplayFor(m => propertyMetdata.Model)
                    </td>
                }
            </tr>
        }
    </tbody>
    
</table>

<span>Showing @Model.Count() items</span>
Then add a Views/Shared/Index.cshtml
@model System.Collections.Generic.IEnumerable<dynamic>
@{
    ViewBag.Title = "Index";
}

@Html.DisplayForModel("Table")

1 comment:

  1. Really thankful to you..after 20 hours of search .. your code solve my problem..i need meta data of table...and this code

    @foreach (var property in ViewData.ModelMetadata.Properties)
    {

    @(property.DisplayName ?? property.PropertyName)
    }

    only works in CRUD View files . For index page i have modified it as you listed...

    @{
         var metadata = ModelMetadata.FromLambdaExpression(m => m.ToArray()[0], ViewData);
        var properties = metadata.Properties;
    }

    @foreach (var property in properties)
    {
    @property.GetDisplayName()
    }

    So it resolved my issue.. Great Thanks

    ReplyDelete