【问题标题】:Best way to get table header names in MVC 4在 MVC 4 中获取表头名称的最佳方法
【发布时间】:2014-09-04 12:13:59
【问题描述】:

我正在尝试在表格中显示对象列表。我可以遍历每个单独的项目以找到它的值(使用 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 中访问其属性的单个项目。

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

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-4


    【解决方案1】:

    抱歉,您的问题有点难以理解,但我认为要点是您想要获取属性的显示名称,用作标题,而不需要或首先必须从列表。

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

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

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

    【讨论】:

    • 是的,这就是我想要实现的。但我知道 DisplayNameFor 但您不能使用它来获取模型中集合内的属性!如果 CLientNumber 是模型本身的一部分,您可以按照您说的做。表头应该从 Innumerable ClientSearchVM 填充,它是模型内的一个属性。那么如何从 CLientSearchVM 类中挖掘并获取表头?我知道这不起作用,但像 Model.ClientSearchVM.ClientNumber ..etc
    • 这就是我要说的。您可以使用它来获取集合成员的属性。 DisplayNameFor 具有内部逻辑来识别它何时传递了一个评估为集合的表达式并检查底层类。
    • 我附上了一张图片。请您看看那张图片并告诉我如何访问 ClientNumber?我根本看不到那个选项。 ClientNumber 是 ClientSearchVM 的一个属性。如图所示,这是模型内部的一个属性。
    • 这似乎只有当你有 IEnumerable&lt;T&gt; 作为你的模型时才会出现这种情况,如果你有一个包装器呢?
    • 这对我不起作用。可能是因为我的模型是 PageModel 的子类,而不是我要列出的东西的集合。不能@Html.DisplayNameFor(m =&gt; m.Users.Name)
    【解决方案2】:

    问题

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

    但是,如果 ClientDetail 集合嵌套在 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)
    

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

    【讨论】:

      猜你喜欢
      • 2010-09-13
      • 1970-01-01
      • 1970-01-01
      • 2010-11-01
      • 1970-01-01
      • 2016-08-25
      • 1970-01-01
      • 2016-03-06
      • 1970-01-01
      相关资源
      最近更新 更多