Ответ 1
Другое подобное обходное решение, которое работает, даже если нет строк, может быть:
...
@{var dummy = Model.FirstOrDefault(); }
<tr>
<th>
@Html.DisplayNameFor(model => dummy.SomeModelProperty)
</th>
...
Это работает для захвата заголовков (NOT VALUES):
@model IEnumerable<SomeModel>
...
<th>@Html.DisplayNameFor(m => m.SomeModelProperty)</th>
Что, если SomeModelProperty:
[Display(Name = "An Excellent Header")]
SomeModelProperty { get; set; }
Затем он отобразит "Отличный заголовок" в элементе заголовка th
.
Вы бы подумали, что это не сработает, потому что модель IEnumerable, у которой не будет m.SomeModelProperty, но она работает, потому что у HtmlHelper есть HtmlHelper<IEnumerable<TModel>>
, так что параметр лямбда TModel
, а не IEnumerable<TModel>
. Поскольку это просто использует метаданные, нет необходимости в элементе из коллекции. (Хотя intellisense на m.
будет лгать вам и заставляет вас думать, что это коллекция). Я не уверен, когда эта прохладная перегрузка была добавлена, но довольно удобна для Index.cshtml и устраняет напуганные вещи, такие как @Html.DisplayNameFor(m => @Model.FirstOrDefault().SomeModelProperty)
, которые я хочу избежать.
http://msdn.microsoft.com/en-us/library/hh833697(v=vs.108).aspx
Однако я не могу понять, как заставить это работать, когда моя модель не IEnumerable, но вместо этого содержит IEnumerable как свойство, например:
public class SomeList
{
public List<SomeModel> SomeModels { get; set; }
public int Page { get; set; }
public DateTime CurrentAsOf { get; set; }
}
Я надеялся быть явным с параметрами типового типа, но я думаю, что параметры типа задаются движком, который просачивается из HtmlHelper, созданного на странице. Можно ли объявить новый HtmlHelper на странице или каким-либо образом указать параметры типа явно?
Index.cshtml:
@model SomeList
//No idea how to do this:
@Html.DisplayNameFor<IEnumerable<SomeModel>>(m => m.SomeModelProperty)
Другое подобное обходное решение, которое работает, даже если нет строк, может быть:
...
@{var dummy = Model.FirstOrDefault(); }
<tr>
<th>
@Html.DisplayNameFor(model => dummy.SomeModelProperty)
</th>
...
У меня точно такая же проблема, потому что я использую ViewModels, поэтому у меня есть ViewModel с IEnumerable фактических объектов как свойство.
Я столкнулся с этим сообщением, где, если вы проверите ответ, парень создал свой собственный HTMLHelper для решения этой проблемы http://forums.asp.net/t/1783733.aspx, Его версия:
public static MvcHtmlString 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);
}
Вам нужно передать два аргумента перечисления и выражения, а не нормальное простое выражение, чтобы вы могли предпочесть ответ @franz. Я не вижу, что в любом случае вам придется пройти 2 аргумента, так как он должен знать, какое свойство модели представления вы применяете для выражения.