How do you access the DisplayNameFor in a nested model

You can create a DisplayTemplate for your InvoiceItems, say "InvoiceItemHeader":

@model IEnumerable<InvoiceItem>

@Html.DisplayNameFor(m => m.Item)
<br />
@Html.DisplayNameFor(m => m.Description)

The type of the model has to be IEnumerable<T>, as the DisplayNameFor Method has an overload version for this type.

Then in your view you can display the template:

 @Html.DisplayFor(m => m.InvoiceItems, "InvoiceItemHeader")
 @foreach (var item in Model.InvoiceItems)
 {
      @Html.DisplayFor(modelItem => item.Item)
      <br />
      @Html.DisplayFor(modelItem => item.Description)
      <br />
 } 

Here you're accessing the item in your loop:

@Html.DisplayFor(modelItem => item.Item)

But here you're not:

@Html.DisplayNameFor(modelItem => modelItem.Item)

Change the latter to this and it should work:

@Html.DisplayNameFor(modelItem => item.Item)

modelItem is of type Invoice (the model passed to the view), but in the loop you want to use item (from the loop iterator) which is of type InvoiceItem.

Side note: Debugging something like this might be a lot more straightforward if everything wasn't called "item." Clear naming is important :)

Edit: If you're accessing it outside of the loop, then you need to drill down into the model manually. Something like this:

@Html.DisplayNameFor(modelItem => modelItem.InvoiceItems.First().Item)

It feels like this would be dangerous, since .First() can throw an exception if there are no items. However, as comments have indicated and some cursory Googling seems to confirm, .First() isn't actually executed at runtime in this case. This is just a bit of trickery to allow .DisplayNameFor() to reflect down into the property.