在MVC 4中获取表头名称的最佳方法

akd*_*akd 5 asp.net-mvc asp.net-mvc-4

我正在尝试在表格中显示对象列表.我可以遍历每个单独的项目以找到它的值(使用for循环或DisplayTemplate),但是我如何非常地选择一个来显示整个组的标题.

这是一个简化的例子:

型号:

public class ClientViewModel
{
    public int Id { get; set; }
    public List<ClientDetail> Details { get; set; }
}
public class ClientDetail
{
    [Display(Name="Client Number")]
    public int ClientNumber { get; set; }
    [Display(Name = "Client Forname")]
    public string Forname { get; set; }
    [Display(Name = "Client Surname")]
    public string Surname { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

视图

@model MyApp.ViewModel.ClientViewModel

@{ var dummyDetail = Model.Details.FirstOrDefault(); }

<table>
    <thead>
        <tr>
            <th>@Html.DisplayNameFor(model => dummyDetail.ClientNumber)</th>
            <th>@Html.DisplayNameFor(model => dummyDetail.Forname)</th>
            <th>@Html.DisplayNameFor(model => dummyDetail.Surname)</th>
        </tr>
    </thead>
    <tbody>
        @for (int i = 0; i < Model.Details.Count; i++)
        {
              <tr>
                <td>@Html.DisplayFor(model => model.Details[i].ClientNumber)</td>
                <td>@Html.DisplayFor(model => model.Details[i].Forname)</td>
                <td>@Html.DisplayFor(model => model.Details[i].Surname)</td>
            </tr>
        }
    </tbody>
</table>
Run Code Online (Sandbox Code Playgroud)

注意:我正在使用var dummyDetail = Model.Details.FirstOrDefault();一个项目,我可以访问其中的属性DisplayNameFor.

  • 访问这些标题的最佳方法是什么?
  • 如果集合为空,这会破坏吗?
  • 我应该用硬编码的纯文本标签替换它们吗?

Kyl*_*Mit 6

问题

正如Thomas所指出的Chris的答案在某些情况下有效,但在使用ViewModel时会遇到麻烦,因为嵌套的属性无法享受相同的自动分辨率。如果您的模型类型为IEnumerable<Type>,则此方法有效,因为DisplayNameFor lambda仍可以访问模型本身的属性:

模型vs枚举<模型>

但是,如果ClientDetail集合嵌套在ViewModel内部,则无法从集合本身获取item属性:

ViewModel内部的集合

解决方案

DisplayNameFor()在Model的List中所指出的,您的解决方案实际上是完美的。如果集合为null,这不会引起任何问题,因为传入的lambda DisplayNameFor从未真正执行过。它仅将其用作表达式树以标识对象的类型。

因此,以下任何一项都可以正常工作

@Html.DisplayNameFor(model => model.Details[0].ClientNumber)

@Html.DisplayNameFor(dummy => Model.Details.FirstOrDefault().ClientNumber)

@{ ClientDetail dummyModel = null; }
@Html.DisplayNameFor(dummyParam => dummyModel.ClientNumber)
Run Code Online (Sandbox Code Playgroud)

进一步说明

如果我们想了解传递表达式所涉及的一些花哨的工作,只需查看DisplayNameFor上的源代码或诸如DescriptionFor的自定义实现即可。这是当我们使用以下不可能的表达式调用DisplayNameFor时发生的简化示例:

 @Html.DisplayNameFor3(model => model.Details[-5].ClientNumber)
Run Code Online (Sandbox Code Playgroud)

剖析表达式树

请注意,我们从model.Details.get_Item(-5).ClientNumberlambda表达式开始,到ClientNumber无需执行表达式就可以仅识别成员()。DisplayAttribute在这种情况下,我们从此处开始使用反射来查找并获取其属性Name