Displaynamefor() from List<Object> in Model

DisplayNameFor() From ListObject in Model

This actually works, even without items in the list:

@Html.DisplayNameFor(model => model.Names[0].FullName)

It works because MVC parses the expression instead of actually executing it. This lets it find that right property and attribute without needing there to be an element in the list.

It's worth noting that the parameter (model above) doesn't even need to be used. This works, too:

@Html.DisplayNameFor(dummy => Model.Names[0].FullName)

As does this:

@{ Namespace.Of.PersonNameViewModel dummyModel = null; }
@Html.DisplayNameFor(dummyParam => dummyModel.FullName)

MVC Html.DisplayNameFor on a complex model

I changed

@Html.DisplayNameFor(m => Model.Addresses.Street)

to

@Html.DisplayNameFor(m => Model.Addresses.FirstOrDefault().Street)

Do not use @Html.DisplayNameFor(m => Model.Addresses[0].Street) because if you need to edit the first row, you won't be able this way.

Everything works as expected now.

How to @Html.DisplayNameFor() on a property of a list’s base class property?

If you can change the property to IEnumerable<BaseModelChildModel>, then you should be able to do:

@Html.DisplayNameFor(m => m.BaseModelChildModels.Foo)

Otherwise, you can index the property. The expression here is not every actually accessed, it's only evaluated to get at the display name. As a result, indexing the property will not cause an error if there's no items in the list as it traditionally would:

@Html.DisplayNameFor(m => m.BaseModelChildModels[0].Foo)

Using DisplayNameFor and DisplayFor whilst looping list within model

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.

Can I have an MVP list use a List inside a model?

I ended up doing it like this:

@model PublicationSystem.ViewModels.ProfileSnapshotListViewModel

<div id="pnlResourceSnapshotEdit">
@{ Html.RenderAction("_ResourceSnapshotEdit", "Profiles", new { id = Model.ResourceAssignedToId }); }
</div>

<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.Snapshots.FirstOrDefault().Salutation)
</th>
</tr>
@foreach (var item in Model.Snapshots) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Salutation)
</td>
</tr>
}
</table>

This gave me the headers and items as I wanted.

What I was looking for was:

@Html.DisplayNameFor(model => model.Snapshots.FirstOrDefault().Salutation)

ASP.NET MVC. How use DisplayNameFor in order to create a table heading and body?

DisplayNameFor() has an overload that accepts IEnumerable<T> so it simply needs to be

<td>@Html.DisplayNameFor(m => m.prop1)</td>

Note that this only works where the the model is Enumerable<T> (in you case @model IEnumerable<Item>).

But will not work if the model was an object containing a proeprty which was IEnumerable<T>.

For example, the following will not work

<td>@Html.DisplayNameFor(m => m.MyCollection.prop1)</td>

and it would need to be

<td>@Html.DisplayNameFor(m => m.MyCollection.FirstOrDefault().prop1)</td>

which will work even if the collection contains no items.

Side note: Under some circumstances, you may initially get a razor error, but you can ignore it. Once you run the app, that error will disappear.

How do you access the DisplayNameFor in a nested model

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.



Related Topics



Leave a reply



Submit