2013-05-22 70 views
19

如何在嵌套模式访问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

谢谢,马克

回答

31

在这里,我们访问在循环的item

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

但在这里你不是:

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

更改后者这一点,它应该工作:

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

modelItem类型为Invoice(将模型传递给视图),但是在循环中要使用InvoiceItem类型的item(来自循环迭代器)。

端注:如果一切不叫调试这样的事情可能是一个很多更直接的“项目”。清除命名很重要:)

编辑:如果您在循环之外访问它,则需要手动深入到模型中。事情是这样的:

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

感觉像这将是危险的,因为如果没有项目.First()可以抛出异常。然而,正如评论所指出的和一些粗略的谷歌搜索似乎确认,.First()不是实际上在这种情况下在运行时执行。这只是一个诡计,允许.DisplayNameFor()反映到财产。

+0

哇,我从来没有注意到它,老老实实在它凝视几分钟的:))) –

+0

Hi-point takere名称 - 但我想在进入循环之前显示DisplayNameFor。目前,如果我按照建议更改它,我会得到“名称'项'在当前上下文中不存在” - 谢谢,Mark – Mark

+1

@fixit:在循环的上下文之外完全是另一回事。你可以尝试类似'modelItem.InvoiceItems.First()。Item'。如果列表为空,那么_might_会抛出一个异常,具体取决于DisplayNameFor的实际工作方式。 (我从来没有偷看它的内部) – David

3

您可以创建一个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 /> 
} 
+0

太棒了! IEnumerable 具有过载的简单认识至关重要。我正在使用ICollection ,只是改变类型在我的情况下造成了所有不同。谢谢! – McArthey

1

我没有试过,但它应该工作。

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

DisplayNameFor扩展方法不是别的,只是期待Memberexpression与此签名的方法:Expression<Func<TModel, TValue>> expression