@ Html.DisplayNameFor для деталей модели - PullRequest
23 голосов
/ 22 февраля 2012

В моей модели у меня есть Entity

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) индексное представление, которое предполагает отображение таблицы Carrier с использованием PagingInfo.

Я пытаюсь использовать Html помощник для отображения Carrier.Name в заголовке моей таблицы Когда я использовал IEnumerable в качестве модели для этого представления, я имел @Html.DisplayFor(model => model.Name)

Как получить тот же результат, используя мой новый CarrierIndexViewModel для отображения заголовка для Carrier.Name?

Ответы [ 5 ]

38 голосов
/ 19 декабря 2013

Я обнаружил, что нет необходимости во вспомогательных методах, дополнительном коде или циклическом просмотре коллекции.Я просто использовал следующее:

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

Это все еще работает, даже если FirstOrDefault() вернет null, поскольку он ищет только метаданные, само свойство Name не доступно.

Большое спасибо @ Kurian , который вдохновил этот ответ.

17 голосов
/ 24 марта 2012

У меня похожая проблема, потому что я не хочу вводить имена столбцов вручную, поэтому я написал помощник:

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; }
}
8 голосов
/ 22 февраля 2012

Вы можете добавить оператор @using в свой View, чтобы указать тип Carrier, затем вам нужно будет пройтись по циклу через свойство Carriers вашей модели.

Ваш View будет выглядеть примерно так ...

@model CarrierIndexViewModel
@using Carrier

@foreach(Carrier c in Model.Carriers)
{
 @Html.DisplayFor(model => c.Name)
}
3 голосов
/ 16 апреля 2015

Вот подход, основанный на оригинальном 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)
2 голосов
/ 17 октября 2012

У меня было похожее требование, но мне нужно было получить отображаемые имена для свойств из другого не перечисляемого класса, чтобы решение из @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).

...