如何在嵌套模型中访问DisplayNameFor

时间:2013-05-22 13:15:32

标签: c# asp.net asp.net-mvc

如何访问嵌套模型中的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

谢谢,Mark

4 个答案:

答案 0 :(得分:35)

在这里,您正在访问循环中的item

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

但在这里你不是:

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

将后者更改为此,它应该有效:

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

modelItem的类型为Invoice(传递给视图的模型),但是在循环中,您希望使用item(来自循环迭代器),类型为{{ 1}}。

旁注:如果所有内容未被称为“项目”,则调试此类内容可能会更简单批次。明确命名很重要:)

编辑:如果您在循环外访问它,则需要手动深入查看模型。像这样:

InvoiceItem

感觉这样会很危险,因为@Html.DisplayNameFor(modelItem => modelItem.InvoiceItems.First().Item) 如果没有项目就会抛出异常。但是,正如评论已经指出并且一些粗略的谷歌搜索似乎证实,.First()在这种情况下不是实际在运行时执行。这只是让.First()反映到该属性中的一些诡计。

答案 1 :(得分:3)

您可以为InvoiceItems创建一个DisplayTemplate,例如“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 />
 } 

答案 2 :(得分:1)

我没试过,但它应该有用。

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

DisplayNameFor扩展方法只是一个期望具有此签名的Memberexpression的方法:Expression<Func<TModel, TValue>> expression

答案 3 :(得分:0)

我知道这很老了,应该发表评论,但是代表:(感觉很糟糕:)

无论如何,我不会担心.First();应该起作用的是,只是创建一个我在DisplayNameFor中引用的虚拟对象。

@model IEnumerable<blah>
@{
  var dummy = new blah();
}
.
.
.
@foreach (var item in Model) 
{
   <div...>
      @Html.DisplayNameFor(model => dummy.Field) 
      @Html.DisplayFor(model => item.Field)
.
.
.
   </div>
}