When I used asp.net mvc 3 scaffolding to make a list. I got a view containing a table. With the headers of that table hard coded in the view. I want to use LabelFor, so I get the l10n I need.
What I tried to do (but failed) was:
@model IEnumerable<User>
<table>
<tr>
<th>
@(Html.LabelFor<User, string>(model => model.Name)) <!--This line errors-->
</th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
</table>
It errors with "IEnumerable does not contain a definition for Name".. etc...
How do I make this work?
Try with some like
@(Html.LabelFor<User, string>(model => model.FirstOrDefault().Name))
Your view model is not adapted to what you are trying to achieve. Here's how a better view model would look like:
public class MyViewModel
{
// This property represents the header value
// you could use data annotations to localize it
[Display(.. some localization here ..)]
public string NameHeader { get; set; }
// This property represents the data source that
// will be used to build the table
public IEnumerable<User> Users { get; set; }
}
and then:
@model MyViewModel
<table>
<tr>
<th>
@Html.LabelFor(x => x.NameHeader)
</th>
</tr>
@foreach (var item in Model.Users) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
</tr>
</table>
and with a display template you don't even need to write a foreach
loop:
@model MyViewModel
<table>
<tr>
<th>
@Html.LabelFor(x => x.NameHeader)
</th>
</tr>
@Html.DisplayFor(x => x.Users)
</table>
and inside the custom display template (~/Views/Shared/DisplayTemplates/User.cshtml
):
@model User
<tr>
<td>@Html.DisplayFor(x => x.Name)</td>
</tr>
You render the Label before (or outside) of the foreach iteration, thus you try to access Name property in an IEnumerable collection which doesn't exist.