Ответ 1
Вы можете попробовать это
@Html.DisplayNameFor(model => model.FirstOrDefault().ItemName)
Я тестировал пакет PagedList, чтобы получить пейджинг для моих представлений индексов. Все шло хорошо, и на уровне контроллера все работает нормально, оно отображает только 5 записей на странице и отображает соответствующую страницу на основе запроса.
Моя проблема в представлении. Я изменил @Model на PagedList.IPagedList
, чтобы получить доступ к Model.HasNextPage
и другим свойствам, но теперь @Html.DisplayNameFor(model => model.ItemName)
больше не работают. Я получаю эту ошибку:
PagedList.IPagedList<Dossier.Models.Item>' does not contain a definition for 'ItemName' and no extension method 'ItemName' accepting a first argument of type 'PagedList.IPagedList<Dossier.Models.Item>' could be found (are you missing a using directive or an assembly reference?)
Вот соответствующие части представления:
@model PagedList.IPagedList<Dossier.Models.Item>
@using Dossier.Models.Item
...
<th>
@Html.DisplayNameFor(model => model.ItemName)
</th>
Кажется, IPagedList несовместим с DisplayNameFor(). Любая идея, почему это происходит, и как я могу это исправить? Я знаю, что могу просто вручную ввести имена столбцов, но мне хотелось бы, чтобы эта информация оставалась (и была изменчивой) в модели позже.
Вы можете попробовать это
@Html.DisplayNameFor(model => model.FirstOrDefault().ItemName)
В качестве альтернативного решения принятого ответа помните, что IPagedList наследует от IEnumerable. Это означает, что вы можете написать:
@model IEnumerable<Dossier.Models.Item>
В начале страницы и просто приведите модель к IPagedList при необходимости:
@Html.PagedListPager((IPagedList)Model, page => Url.Action("Index", new { page = page }))
Вы даже можете объявить переменную casted в заголовке, чтобы использовать ее несколько раз на странице:
@{
ViewBag.Title = "My page title";
var pagedlist = (IPagedList)Model;
}
Это позволит вам использовать метод DisplayNameFor helper и получить доступ ко всем методам/свойствам PagedList, без необходимости использования фиктивных элементов или вызова .FirstOrDefault() для каждого поля.
Я решил проблему, создав перегрузку DisplayNameFor
, которая принимает IPagedList<TModel>
.
namespace PagedList.Mvc
{
public static class Extensions
{
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
public static MvcHtmlString DisplayNameFor<TModel, TValue>(this HtmlHelper<IPagedList<TModel>> html, Expression<Func<TModel, TValue>> expression)
{
return DisplayNameForInternal(html, expression);
}
[SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", Justification = "This is an extension method")]
internal static MvcHtmlString DisplayNameForInternal<TModel, TValue>(this HtmlHelper<IPagedList<TModel>> html, Expression<Func<TModel, TValue>> expression)
{
return DisplayNameHelper(ModelMetadata.FromLambdaExpression(expression, new ViewDataDictionary<TModel>()),
ExpressionHelper.GetExpressionText(expression));
}
internal static MvcHtmlString DisplayNameHelper(ModelMetadata metadata, string htmlFieldName)
{
string resolvedDisplayName = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
return new MvcHtmlString(HttpUtility.HtmlEncode(resolvedDisplayName));
}
}
}
Я отправлю запрос на перенос в проект PageList, чтобы включить его в проект для всех.
Вам не нужно менять @Html.DisplayNameFor
. Объявите модель в представлении как:
@model IEnumerable<Dossier.Models.Item>
Просто переместите пейджер на частичный просмотр (давайте назовите его "_Pager" ):
@model IPagedList
...
@Html.PagedListPager(Model,
page => Url.Action("Index", new { page, pageSize = Model.PageSize }))
...
Отметьте пейджер в своем представлении:
@Html.Partial("_Pager", Model)
Вот оно.
P.S. Вы можете создать Html-помощник вместо частичного представления...