如何在运行时从Display(Name =)DataAnnotation获取强类型列表支架视图的列标题?

toe*_*ens 17 asp.net-mvc razor asp.net-mvc-3

如何[Display(Name="Some Title")]在List scaffold视图的输出中获取DataAnnotations"Some Title"?

我为这个类创建了一个强类型列表支架视图:

public class CompanyHoliday
{
    [Key]
    public int Id { get; set; }

    [Required]
    [Display(Name = "Datum")]
    [DataType(System.ComponentModel.DataAnnotations.DataType.Date)]
    public DateTime Date { get; set; }

    [Required]
    [StringLength(50)]
    [Display(Name = "Feiertag Name")]
    public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

该视图如下所示:

@model IEnumerable<Zeiterfassung.Domain.CompanyHoliday>

@{
    ViewBag.Title = "Year";
}

<h2>Year</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
    <th></th>
    <th>
        Date
    </th>
    <th>
        Name
    </th>
</tr>

@foreach (var item in Model) {
<tr>
    <td>
        @Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
        @Html.ActionLink("Details", "Details", new { id=item.Id }) |
        @Html.ActionLink("Delete", "Delete", new { id=item.Id })
    </td>
    <td>
        @String.Format("{0:g}", item.Date)
    </td>
    <td>
        @item.Name
    </td>
</tr>
}

</table>
Run Code Online (Sandbox Code Playgroud)

但是,我不希望表头中有"Date"和"Name".我希望动态渲染"Datum"和"Feiertag Name".

实际列标题标题应来自Display DataAnnotation.

我该怎么做呢?

Cod*_*ike 18

一个古老的话题,但我想出了一个扩展方法来处理这个问题.

让我们说我的模型是:

public class MyModel
{
    [Display(Name = "Some Property")]
    public string SomeProp { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

将此方法放入静态类:

namespace Web.Extensions
{
    public static class HtmlHelperExtensions
    {
        public static MvcHtmlString DisplayNameFor<TModel, TProperty>(this HtmlHelper<IEnumerable<TModel>> helper, Expression<Func<TModel, TProperty>> expression)
        {
            var name = ExpressionHelper.GetExpressionText(expression);
            name = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
            var metadata = ModelMetadataProviders.Current.GetMetadataForProperty(() => Activator.CreateInstance<TModel>(), typeof(TModel), name);
            return new MvcHtmlString(metadata.DisplayName);
        }
    } 
}
Run Code Online (Sandbox Code Playgroud)

然后在你的View中,IEnumerable<MyModel>你可以像这样使用它:

@using Web.Extensions
@model IEnumerable<MyModel>

<table>
    <tr>
        <th>
            @Html.DisplayNameFor(m => m.AvgElecCost)
        </th>
Run Code Online (Sandbox Code Playgroud)

生成的HTML将是:

        <th>
            Some Property
        </th>
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你!

  • 我将整个文件(还包含更多方法)添加到Gist:https://gist.github.com/1379767#file_html_helper_display_name_extensions.cs享受! (4认同)
  • 太棒了,我要把这个扩展名添加到我的工具箱中! (2认同)
  • +1 - 实际上,似乎这个重载现在被[MVC 4]中的标准脚手架使用(http://msdn.microsoft.com/en-us/library/system.web.mvc.html.displaynameextensions(v = vs.108)的.aspx).示例[此处](http://stackoverflow.com/questions/4709367/is-it-possible-to-use-labelfor-for-header-row-in-index-view#13305681) (2认同)

Aar*_*nLS 14

这是我遵循的模式.这假设Lists永远不为null,但可以为空,但条件很容易被短路列为空列表.我确实喜欢Brian的扩展方法.

@if (Model.BurgersList.Count > 0)
{
  var meta = Model.BurgersList.First();
   <table>
        <tr>
            <th>
                @Html.DisplayNameFor(m => meta.Title)
            </th>
            <th>
                @Html.DisplayNameFor(m => meta.HasMustard)
            </th>
         //etc....
   @foreach (var item in Model.AssignmentDefinitions)
   {
        <tr>
            <td>
                @Html.DisplayFor(m => item.Title)
            </td>
            <td>
                @Html.DisplayFor(m => item.HasMustard)
            </td>
       //etc...
   }
   </table>
}
else
{ 
    @:No burgers available.  Create(usually make this an action link)  a new one.
}
Run Code Online (Sandbox Code Playgroud)