Using @Html.DisplayNameFor() with PagedList

I solved the problem by creating an overload of DisplayNameFor that accepts a 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));
        }
    }
}

I'll be sending a pull request to PageList project to include it into the project for everyone.


As an alternate solution to the accepted answer, remember that IPagedList inherits from IEnumerable. That means that you could write:

@model IEnumerable<Dossier.Models.Item>

At the beginning of the page, and just cast the model to IPagedList when needed:

@Html.PagedListPager((IPagedList)Model, page => Url.Action("Index", new { page = page }))

You can even declare the casted variable in the header, in order to use it multiple times within the page:

@{
    ViewBag.Title = "My page title";
    var pagedlist = (IPagedList)Model;
}

This would allow you to use the DisplayNameFor helper method, and access all PagedList methods/properties, without the need for dummy elements nor calling .FirstOrDefault() for each field.


You can try this

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

You do not need to change @Html.DisplayNameFor. Declare model in the view as:

@model IEnumerable<Dossier.Models.Item>

Just move your pager to partial view (lets name it "_Pager"):

@model IPagedList

...

@Html.PagedListPager(Model, 
   page => Url.Action("Index", new { page, pageSize = Model.PageSize }))

...

Render the pager in your view:

@Html.Partial("_Pager", Model)

Thats it.

P.S. You can create Html helper instead of partial view...