Подтвердить что ты не робот

Как получить доступ к 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

Спасибо, Марк

4b9b3361

Ответ 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