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

时间:2014-07-14 14:30:21

标签: 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; }
}

查看

@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>

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

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

2 个答案:

答案 0 :(得分:5)

问题

作为Thomas pointed outChris's answer在某些情况下有效,但在使用ViewModel时会遇到麻烦,因为嵌套属性不会享受相同的自动分辨率。如果模型类型为IEnumerable<Type>,则此方法有效,因为DisplayNameFor lambda仍然可以访问模型本身的属性:

Model vs Enum<Model>

但是,如果ClientDetail集合嵌套在ViewModel中,我们无法从集合本身获取项目属性:

Collection inside ViewModel

解决方案

正如DisplayNameFor() From List in Model所指出的,你的解决方案实际上非常好。如果集合为null,则不会导致任何问题,因为传递到DisplayNameFor的lambda永远不会被实际执行。它只将它用作表达式树来识别对象的类型。

以下任何一项工作正常

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

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

@{ ClientDetail dummyModel = null; }
@Html.DisplayNameFor(dummyParam => dummyModel.ClientNumber)

进一步说明

如果我们想看到传递表达式所涉及的一些花哨的步法,只需查看DisplayNameFor上的源代码或DescriptionFor等自定义实现。这是我们使用以下不可能的表达式调用DisplayNameFor时会发生什么的简化示例:

 @Html.DisplayNameFor3(model => model.Details[-5].ClientNumber)

Dissecting the Expression Tree

注意我们如何从lambda表达式中的model.Details.get_Item(-5).ClientNumber转到只能识别成员(ClientNumber)而不执行表达式。从那里,我们只使用反射来查找DisplayAttribute并获取其属性,在本例中为Name

答案 1 :(得分:1)

很抱歉,您的问题有点难以理解,但我认为要点是您希望获取属性的显示名称,用作标题,而不需要或首先必须从中选择特定项目。列表。

已经内置了对此的支持。您只需使用模型本身:

@Html.DisplayNameFor(m => m.ClientNumber)

换句话说,就是不要使用特定的实例。 DisplayNameFor具有检查列表所基于的类以获取属性的逻辑。