web-dev-qa-db-fra.com

Utilisation de @ Html.DisplayNameFor () avec PagedList

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.

43
nb_

Vous pouvez essayer ceci

@Html.DisplayNameFor(model => model.FirstOrDefault().ItemName)
76
ViniciusdeLemos

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.

36
salgiza

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.

4
CodeClimber

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 ...

1