2

I have created a ViewModel which I am using as the model for my view. Within the view model it contains the following definition:

public class ItemDetailViewModel
{
    public int ItemId { get; set; }
    public bool Active { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public List<ItemDetailItemOptionViewModel> ItemOptions { get; set; }
}

As you can see it contains a List<> named ItemOptions. My view model is tied to ItemDetailViewModel. Within the view I loop through each element in the list and output them:

@model app1.Models.ViewModels.ItemDetailViewModel

@{
    ViewBag.Title = "Item " + @Html.DisplayFor(model => model.ItemId);
}

//...
<thead>
    <tr>
        <th>Active</th>
        <th>Names</th>
    </tr>
</thead>
<tbody>
    @foreach (app1.Models.ViewModels.ItemDetailItemOptionViewModel ItemOption in Model.ItemOptions)
    {
        <tr>
            <td>@ItemOption.Active</td>
            <td>@ItemOption.Name</td>
        </tr>
    }
</tbody>
//...

What I want to be able to do is instead of hard coding the name and values, I want to be able to user the helpers I use else where within the page, such as:

@Html.DisplayNameFor(model => model.ItemCode)
@Html.DisplayFor(model => model.ItemCode)

I've tried the following

@Html.DisplayNameFor(model => model.ItemOptions.ItemCode)
@Html.DisplayFor(model => model.ItemOptions.ItemCode)

But this gives the following error:

Error 1 'System.Collections.Generic.List<[].Models.ViewModels.ItemDetailItemOptionViewModel>' does not contain a definition for 'ItemCode' and no extension method 'ItemCode' accepting a first argument of type 'System.Collections.Generic.List<[].Models.ViewModels.ItemDetailItemOptionViewModel>' could be found (are you missing a using directive or an assembly reference?) ....\Views\Item\Details.cshtml 87 81 []

I've also tried doing it off the ItemOption object which I loop on but get similar issues. What am I doing wrong?

Joseph
  • 2,706
  • 6
  • 42
  • 80
  • Going from the `ItemOption` should work fine: `@Html.DisplayNameFor(model => ItemOption.ItemCode) @Html.DisplayFor(model => ItemOption.ItemCode)` – nemesv Dec 30 '13 at 19:38
  • Ah yes, the DisplayFor works fine within the loop. How would I reference the headers though as this is outside the loop so I don't have ItemOption set. – Joseph Dec 30 '13 at 19:40
  • You can use Partial View Templates. See this for some details on how to go about doing that. http://stackoverflow.com/a/2326405/1181408 – cgotberg Dec 30 '13 at 19:49

1 Answers1

4

ItemOptions is a List<>, so by itself it doesn't have a definition for ItemCode. Any element in that list, however, does. Something like this:

@Html.DisplayNameFor(model => model.ItemOptions.First().ItemCode)
@Html.DisplayFor(model => model.ItemOptions.First().ItemCode)

At first it might look like this would potentially throw an error if the list has no elements, but it's a quirk of the view engine that it doesn't actually call .First() on the list, it just uses the reference to determine the type from which it gleans information. The type returned by First() is ItemDetailItemOptionViewModel in this case, so it then gets the meta-data it needs from that type.

David
  • 208,112
  • 36
  • 198
  • 279