@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?
Ответы
Ответ 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).