【问题标题】:@Html.DisplayNameFor for details model@Html.DisplayNameFor 了解详情模型
【发布时间】:2012-03-12 07:40:42
【问题描述】:

在我的模型中我有一个实体

public class Carrier
{
public Guid CarrierId { get; set; }
public string Name { get; set; }
}

我也有一个 ViewModel

public class CarrierIndexViewModel
{
public IEnumerable<Carrier> Carriers { get; set; }
public PagingInfo PagingInfo { get; set; }
}

我有一个强类型 (CarrierIndexViewModel) 索引视图,假设它使用 PagingInfo 显示一个 Carrier 表。

我正在尝试使用 Html 助手在我的表格标题中显示 Carrier.Name 当我使用 IEnumerable 作为这个视图的模型时,我有 @Html.DisplayFor(model =&gt; model.Name)

如何使用我的新 CarrierIndexViewModel 显示 Carrier.Name 的标题来获得相同的结果?

【问题讨论】:

    标签: asp.net-mvc razor html-helper


    【解决方案1】:

    您可以在视图中添加 @using 语句来指定 Carrier 类型,然后您将需要遍历模型的 Carriers 属性。

    您的视图将类似于..

    @model CarrierIndexViewModel
    @using Carrier
    
    @foreach(Carrier c in Model.Carriers)
    {
     @Html.DisplayFor(model => c.Name)
    }
    

    【讨论】:

      【解决方案2】:

      我也遇到了类似的问题,因为我不想手动输入列名,所以我写了一个助手:

      public static IHtmlString DisplayColumnNameFor<TModel, TClass, TProperty>
          (this HtmlHelper<TModel> helper, IEnumerable<TClass> model,
          Expression<Func<TClass, TProperty>> expression)
      { 
          var name = ExpressionHelper.GetExpressionText(expression);
          name = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
          var metadata = ModelMetadataProviders.Current.GetMetadataForProperty(
              () => Activator.CreateInstance<TClass>(), typeof(TClass), name);
      
          return new MvcHtmlString(metadata.DisplayName);
      }
      

      然后在视图中你会调用它

      @Html.DisplayColumnNameFor(Model.Carriers, m => m.Name)
      

      请注意,您可以使用 Display 属性,它接受名称和许多其他自定义,如资源文件等。

      public class Carrier
      {
        [Display(Name="Carrier ID")]
        public Guid CarrierId { get; set; }
        [Display(Name="Carrier Name")]
        public string Name { get; set; }
      }
      

      【讨论】:

      • 我还没试过,但我想你可以说“m => m.Carriers[0].Name”。由于它在内部使用来自 lambda 表达式的元数据,因此“Carriers”是 null 还是空都无关紧要。
      • 我可以建议稍微调整一下吗?如果尚未应用显示名称属性,您需要像这样返回属性名称:“return new MvcHtmlString(metadata.DisplayName ?? name)”
      • 我喜欢这个解决方案背后的想法,但是当我想到它时,我觉得我听到了一些警报(也许我不应该考虑它:))。如果我要花时间在我的代码中为某个属性编写显示值,为什么不花时间在视图中编写显示值呢?似乎编写了更多代码只是为了防止向视图中插入值,而实际上它应该在哪里。
      • @phreak3eb 如果你想硬核价值,那就去做吧。我使用了这种方法,因此我可以本地化 [Display(Name="Some name")] 并避免硬编码。您可以在这里查看 *.resx 解决方案stackoverflow.com/a/20383378/1241400
      • @plurby 好的,这是一个更好的方法。更好的是它支持本地化! :)
      【解决方案3】:

      我有类似的要求,但我需要从不同的不可枚举类中获取属性的显示名称,这样@plurby 的解决方案就行不通了。我最终通过创建一个流畅的调用来解决这个问题,该调用可用于为任何任意类型获取新的 HtmlHelper。扩展和适配器的代码是:

      public static class HtmlHelpers
      {
          public static HtmlHelperAdapter<TModel> Adapt<TModel>(this HtmlHelper<TModel> helper)
          {
              return new HtmlHelperAdapter<TModel>(helper);
          }
      
          public class HtmlHelperAdapter<TModel>
          {
              private readonly HtmlHelper<TModel> _helper;
      
              public HtmlHelperAdapter(HtmlHelper<TModel> helper)
              {
                  _helper = helper;
              }
      
              public HtmlHelper<TNewModel> For<TNewModel>()
              {
                  return new HtmlHelper<TNewModel>(_helper.ViewContext, new ViewPage(), _helper.RouteCollection);
              }
          }
      }
      

      然后您可以像这样在视图中使用它:

      <td>@(Html.Adapt().For<MyOtherModel>().DisplayNameFor(m => m.SomeProperty))</td>
      

      其中一个优点是这种方法适用于任何 HtmlHelper 扩展,而不仅仅是 DisplayNameFor(但请记住,改编后的 HtmlHelper 没有任何视图数据,因为这些都是基于在视图,因此在改编后的 HtmlHelper 中不起作用)。

      【讨论】:

        【解决方案4】:

        我发现不需要辅助方法、额外代码或循环遍历集合。我刚刚使用了以下内容:

        @Html.DisplayNameFor(model => model.Carriers.FirstOrDefault().Name)
        

        即使FirstOrDefault() 会返回null,这仍然有效,因为它只是在寻找元数据,Name 属性本身未被访问。

        非常感谢@Kurian 启发了这个答案。

        【讨论】:

        • 谢谢。正是我一直在寻找的。如果 Carriers 是一个列表,您可以使用 Carriers[0] 或 Carriers.FirstOrDefault() 。
        【解决方案5】:

        这是一种方法,它基于原始 DisplayNameFor 扩展方法并且工作一致

        HtmlHelper的扩展方法:

        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Linq.Expressions;
        using System.Web;
        using System.Web.Mvc;
        
        public static class HtmlHelperExtensions
        {
            public static MvcHtmlString DisplayNameFor<TModel, TEnumerable, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, IEnumerable<TEnumerable>>> enumerableExpression, Expression<Func<TEnumerable, TValue>> valueExpression)
            {
                var metadata = ModelMetadata.FromLambdaExpression(valueExpression, new ViewDataDictionary<TEnumerable>());
                string displayName = metadata.DisplayName ?? metadata.PropertyName ?? ExpressionHelper.GetExpressionText(valueExpression).Split('.').Last();
                return new MvcHtmlString(HttpUtility.HtmlEncode(displayName));
            }
        }
        

        这就是它在视图中的使用方式:

        @Html.DisplayNameFor(m => m.Carriers, c => c.Name)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-03-03
          • 1970-01-01
          • 1970-01-01
          • 2014-10-05
          • 2015-12-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多