Подтвердить что ты не робот

@Html.DisplayNameFor для подробной модели

В моей модели у меня есть 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?

4b9b3361

Ответ 1

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

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

@model CarrierIndexViewModel
@using Carrier

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

Ответ 2

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

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

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

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

Ответ 3

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

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; }
}

Ответ 4

Вот подход, основанный на методе расширения оригинал 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)

Ответ 5

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