I’m having trouble figuring out a clean way to do this. I have a ViewModel class that contains a collection of rows for a table. I would like to be able to do an @Html.DisplayNameFor() on the type in the strongly-typed collection without referring to the first item in the collection or creating a new instance of the type. So to clarify here’s an example:
public class TableViewModel
{
public string Title { get; set; }
public IEnumerable<Row> Rows { get; set; }
}
public class Row
{
public int ColumnA { get; set; }
public int ColumnB { get; set; }
}
//In the Razor view
<table>
<tr>
<th>@Html.DisplayNameFor(???)</th>
</tr>
</table>
Is there a way to do this without doing @Html.DisplayNameFor(x => x.Rows.First().ColumnA)?
You could use the
this.ViewData.ModelMetadata.Propertiescollection and call theGetDisplayNamemethod to generate the header cell content. We do this generically in our code to render an arbitrary model as a table.Edit:
To expand on this, I use a basic model that represents a table and only a table. I have 3 classes defined. I have a
TableRowCell' class, aTableRow’ class (which is essentially a collection ofTableRowCellobjects) and aTableclass.When I have a view model that contains a collection of objects that I want to display in a table I call first an
HtmlHelperextension that converts that collection into aTableobject. Inside that method I iterate over a call toModelMetadataProviders.Current.GetMetadataForType(null, typeof(TModel)).Properties..Where(item => item.ShowForDisplay)to get a collection of metadata objects used to generate the header cells. I then iterate over the collection of items and callModelMetadataProviders.Current.GetMetadataForType(() => item, typeof(TModel)).Properties..Where(item => item.ShowForDisplay)to get a collection of metadata objects used to generate the content cells.Technically, my
HtmlHelperextension method actually returns aTableBuilderobject which will has a method calledRenderon it which generates the html. That setup has served me well so far.