web-dev-qa-db-ja.com

PagedListで@ Html.DisplayNameFor()を使用する

インデックスビューのページングを取得するために、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()と互換性がないようです。なぜこれが起こっているのか、どのように修正できるのでしょうか?列名を手動で入力できることはわかっていますが、その情報を後でモデルにとどめて(そして変更可能に)したいのです。

43
nb_

これを試すことができます

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

受け入れられた答えの代替ソリューションとして、IPagedListはIEnumerableを継承することに注意してください。つまり、次のように書くことができます。

@model IEnumerable<Dossier.Models.Item>

ページの先頭で、必要に応じてモデルをIPagedListにキャストします。

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

ページ内で複数回使用するために、ヘッダーでキャスト変数を宣言することもできます。

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

これにより、DisplayNameForヘルパーメソッドを使用し、ダミー要素や各フィールドの.FirstOrDefault()を呼び出すことなく、すべてのPagedListメソッド/プロパティにアクセスできます。

36
salgiza

IPagedList<TModel>を受け入れるDisplayNameForのオーバーロードを作成することで問題を解決しました。

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プロジェクトにプルリクエストを送信して、全員のプロジェクトに含めるようにします。

4
CodeClimber

変更する必要はありません@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)

それでおしまい。

追伸部分ビューの代わりにHtmlヘルパーを作成できます...