インデックスビューのページングを取得するために、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 }))
ページ内で複数回使用するために、ヘッダーでキャスト変数を宣言することもできます。
@{
ViewBag.Title = "My page title";
var pagedlist = (IPagedList)Model;
}
これにより、DisplayNameForヘルパーメソッドを使用し、ダミー要素や各フィールドの.FirstOrDefault()を呼び出すことなく、すべてのPagedListメソッド/プロパティにアクセスできます。
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プロジェクトにプルリクエストを送信して、全員のプロジェクトに含めるようにします。
変更する必要はありません@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ヘルパーを作成できます...