Как получить доступ к DisplayNameFor в вложенной модели
Как вы получаете доступ к DisplayNameFor
во вложенной модели - то есть.:
public class Invoice
{
public int InvoiceId { get; set; }
public string CustomerName { get; set; }
public string Contact { get; set; }
public IList<InvoiceItem> InvoiceItems { get; set; }
}
public class InvoiceItem
{
public int InvoiceItemId { get; set; }
public int InvoiceId { get; set; }
[Display(Name = "Item Heading")]
public string Item { get; set; }
[Display(Name = "Item Description")]
public string Description { get; set; }
public virtual Invoice Invoice { get; set; }
}
Я могу перебирать вложенные элементы следующим образом:
@foreach (var item in Model.InvoiceItems)
{
@Html.DisplayFor(modelItem => item.Item)
<br />
@Html.DisplayFor(modelItem => item.Description)
<br />
}
Но как мне добраться до: [Display(Name = "Item Heading")]
@Html.DisplayNameFor(modelItem => modelItem.Item)
Я получаю ошибку: 'inv5.Models.Invoice' does not contain a definition for 'Item' and no extension method 'Item' accepting a first argument of type 'inv5.Models.Invoice' could be found
Спасибо, Марк
Ответы
Ответ 1
Здесь вы получаете доступ к item
в своем цикле:
@Html.DisplayFor(modelItem => item.Item)
Но здесь вы не:
@Html.DisplayNameFor(modelItem => modelItem.Item)
Измените последнее на это, и оно должно работать:
@Html.DisplayNameFor(modelItem => item.Item)
modelItem
имеет тип Invoice
(модель передана в представление), но в цикле вы хотите использовать item
(из итератора цикла), который имеет тип InvoiceItem
.
Боковое примечание. Отладка чего-то подобного может быть намного проще, если все не было названо "элементом". Четкое именование важно:)
Изменить:. Если вы обращаетесь к нему за пределами цикла, вам необходимо вручную перейти к модели. Что-то вроде этого:
@Html.DisplayNameFor(modelItem => modelItem.InvoiceItems.First().Item)
Похоже, это было бы опасно, поскольку .First()
может генерировать исключение, если нет элементов. Однако, как отмечали комментарии, и некоторый поверхностный подход к Google, похоже, подтверждает, .First()
на самом деле не выполняется во время выполнения в этом случае. Это всего лишь немного обман, чтобы позволить .DisplayNameFor()
отразиться в свойстве.
Ответ 2
Вы можете создать DisplayTemplate для своего InvoiceItems
, например "InvoiceItemHeader":
@model IEnumerable<InvoiceItem>
@Html.DisplayNameFor(m => m.Item)
<br />
@Html.DisplayNameFor(m => m.Description)
Тип модели должен быть IEnumerable<T>
, так как DisplayNameFor Method имеет версию перегрузки для этого типа.
Затем в вашем представлении вы можете отобразить шаблон:
@Html.DisplayFor(m => m.InvoiceItems, "InvoiceItemHeader")
@foreach (var item in Model.InvoiceItems)
{
@Html.DisplayFor(modelItem => item.Item)
<br />
@Html.DisplayFor(modelItem => item.Description)
<br />
}
Ответ 3
Я не пробовал это, но он должен работать.
@Html.DisplayNameFor(modelItem => modelItem.First().InvoiceItems().First().Item)
DisplayNameFor метод расширения - это не что иное, как метод, ожидающий выражения с помощью этой подписи: Expression<Func<TModel, TValue>> expression