J'ai essayé le package PagedList pour obtenir la pagination pour mes vues d'index. Tout se passait bien, et au niveau du contrôleur, tout fonctionne bien, il n'affiche que 5 enregistrements par page et affiche la page appropriée en fonction de la chaîne de requête.
Mon problème est dans la vue. J'ai changé le @Model en PagedList.IPagedList
Pour pouvoir accéder au Model.HasNextPage
Et à d'autres propriétés, mais maintenant la @Html.DisplayNameFor(model => model.ItemName)
ne fonctionne plus. Je reçois cette erreur:
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?)
Voici les parties pertinentes de la vue:
@model PagedList.IPagedList<Dossier.Models.Item>
@using Dossier.Models.Item
...
<th>
@Html.DisplayNameFor(model => model.ItemName)
</th>
Il semble que IPagedList n'est pas compatible avec DisplayNameFor (). Une idée de pourquoi cela se produit et comment je pourrais y remédier? Je sais que je pourrais simplement saisir manuellement les noms des colonnes, mais j'aimerais que ces informations restent (et puissent être modifiées) dans le modèle plus tard.
Vous pouvez essayer ceci
@Html.DisplayNameFor(model => model.FirstOrDefault().ItemName)
Comme solution alternative à la réponse acceptée, n'oubliez pas que IPagedList hérite de IEnumerable. Cela signifie que vous pouvez écrire:
@model IEnumerable<Dossier.Models.Item>
Au début de la page, et transtypez simplement le modèle sur IPagedList si nécessaire:
@Html.PagedListPager((IPagedList)Model, page => Url.Action("Index", new { page = page }))
Vous pouvez même déclarer la variable castée dans l'en-tête, afin de l'utiliser plusieurs fois dans la page:
@{
ViewBag.Title = "My page title";
var pagedlist = (IPagedList)Model;
}
Cela vous permettrait d'utiliser la méthode d'assistance DisplayNameFor et d'accéder à toutes les méthodes/propriétés PagedList, sans avoir besoin d'éléments factices ni appeler .FirstOrDefault () pour chaque champ.
J'ai résolu le problème en créant une surcharge de DisplayNameFor
qui accepte un 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));
}
}
}
J'enverrai une demande d'extraction au projet PageList pour l'inclure dans le projet pour tout le monde.
Vous n'avez pas besoin de changer @Html.DisplayNameFor
. Déclarez le modèle dans la vue comme:
@model IEnumerable<Dossier.Models.Item>
Déplacez simplement votre pager en vue partielle (appelons-le "_Pager"):
@model IPagedList
...
@Html.PagedListPager(Model,
page => Url.Action("Index", new { page, pageSize = Model.PageSize }))
...
Rendez le pager à votre vue:
@Html.Partial("_Pager", Model)
C'est ça.
P.S. Vous pouvez créer un assistant HTML au lieu d'une vue partielle ...