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
Why Doesn't Xmlserializer Support Dictionary
Differencebetween Server.Mappath and Hostingenvironment.Mappath
Httpclient Not Supporting Postasjsonasync Method C#
C#: Prepending to Beginning of a File
How to Sort a String of Text Followed by a Number Using Linq
Objects in Scene Dark After Calling Loadscene/Loadlevel
How to Pass Data from Mainwindow to a User Control That's Inside the Mainwindow
Shellexecute Equivalent in .Net
Print Webbrowser Without Previewing I.E. Single Click Print
Datetime Conversion from String C#
How to Make the Value of a Variable Track the Value of Another
Textrenderer.Measuretext and Graphics.Measurestring Mismatch in Size