CategoryフィルターとItemsPerPageに基づいて、製品のフィルターされたリストを表示しようとしていますが、PagedListで使用しようとすると問題が発生します。
PagedListの専門知識を持っている人は、自分のページネーションコードを書く必要がある場合や、PagedListを使用して必要な結果を取得する方法がある場合、アドバイスをくれます。
現在のページに表示する必要がある行数のみを取得するためにLINQのスキップアンドテイク機能を使用していますが、フィルターの合計数に基づいてページを表示するにはページングリンクが必要です。
例:私の検索フィルターは50の結果を見つけますが、ページごとの行は10項目であるため、LINQのSkip()とTake()を使用して10行のみを取得します。 View.cshtmlにページリンクを表示する必要があります<< 1 | 2 | 3 | 4 | 5 >>デフォルトのPagedListでは、現時点では<< 1> >、1ページしか表示されない理由はわかっていますが、結果のサブセットのみを取得しながら、正しい数のページリンクを表示できるようにする方法を知りたいだけです。
**私の目標は、Webページの応答パフォーマンスが高速になるように、最適化されたクエリをデータベースに書き込むことです。
アクションメソッドのコードは次のようになります。コードは正しい結果を得ていますが、ページネーションは私が必要としているように機能していません:
public ViewResult List(int page =1, string category =null)
{
if (category != null) this.CurrentCategory = category;
var products = repository.Products
.Where(p => this.CurrentCategory == null || p.Category == this.CurrentCategory)
.OrderBy(p => p.ProductID)
.Skip((page -1) * PageSize)
.Take(PageSize);
return View(products.ToList().ToPagedList(page, PageSize));
}
ページネーションを処理するビューのコードスニペットを次に示します。プロジェクトのGithubサイトを調べましたが、カスタムページを提供するための拡張メソッドが見つかりませんでした。 「ページあたりのアイテム」と@Modelの製品のCount()に基づいてページ数のみをレンダリングすると思います:
@model IPagedList<Product>
//foreach loop that renders the @Model
//Code that displays the pagination using PagedList
<div style="text-align:center">
@Html.PagedListPager(Model, page => Url.Action("List", new { page = page, category = ViewBag.CurrentCategory }), PagedListRenderOptions.OnlyShowFivePagesAtATime
)
</div>
私はまったく同じ問題を抱えていたため、StaticPagedListを使用することになりました。このようなことができます
public ViewResult List(int page =1, string category =null)
{
if (category != null) this.CurrentCategory = category;
var products = repository.Products
.Where(p => this.CurrentCategory == null || p.Category == this.CurrentCategory)
.OrderBy(p => p.ProductID)
.Skip((page -1) * PageSize)
.Take(PageSize);
var count = repository.Products
.Where(p => this.CurrentCategory == null || p.Category == this.CurrentCategory).Count();
var resultAsPagedList = new StaticPagedList<Product>(products, page, PageSize, count);
return View(resultAsPagedList);
}
ビューについては、モデルタイプを置き換えるだけです
@model StaticPagedList<Product>
ToPagedList
はTake
とSkip
を内部で使用し、IQueryable<T>
クラスの拡張を使用すると、必要なデータベースクエリが生成されます。また、TotalItemCount
をメタデータに取得します。
Sqlに変換できないメソッドを使用しているため、クエリ結果をメモリに取り込む必要がある場合があります。つまり、PagedList
をEnumerable
に戻す必要があります。この問題を回避するには、次のようなStaticPagedList
メソッドを使用します。
var superset= repository.Products
.Where(p => this.CurrentCategory == null
|| p.Category == this.CurrentCategory)
.OrderBy(p => p.ProductID)
.ToPagedList(page, PageSize);
var subset = superset
.AsEnumerable()
.Select(p => new ProductViewModel
{
OtherData = p.UntranslateableMethod()
})
var model = new StaticPagedList<ProductViewModel>(subset,
superset.GetMetaData());
}
コメントのメソッドの要約から:
すでに分割されたサブセットと、スーパーセットのサイズとその中のサブセットの位置に関する情報を含むPagedList.StaticPagedListクラスの新しいインスタンスを初期化します。
それでも、カウントを個別に要求する必要があります。
var products = repository.Products
.Where(p => this.CurrentCategory == null || p.Category == this.CurrentCategory);
var numProds = products.Count();
var mypage = products.OrderBy(p => p.ProductID)
.Skip((page -1) * PageSize)
.Take(PageSize);
PagedListのメソッドを使用する場合、LINQ .skip()
および.take()
も使用する必要はありません。そうすると、リストを事前に制限していることになり、ライブラリを使用しても意味がありません。最初にリストをフィルタリングして.skip()
と.take()
は、それらのpagesize
の結果を再度フィルター処理してpagesize
に渡します。これはもちろん同じですが、PagedListは合計がわからないのです。
すべての結果をロードしないようにする場合は、IQueryable
またはEnumerable
ではなく、List
をPagedListに送信するだけです。 PagedListは.Skip()
と.Take()
を追加し、データベースはそれらの結果のみを返します。
上記の説明は正しいです。ただし、静的選択リストを割り当てる場合は..
new StaticPagedList<Product>(products, page, PageSize, count);.
実際のカウントから表示されるページリンクの数が少なくなります。カウントが10の場合、ページサイズが5であれば2ページのみが表示されます。
すべてのページリンクをカウントして表示する場合は、
pass count*5 ie count*pagesize
new StaticPagedList<Product>(products, page, PageSize, count*5);//in my case page size is 5
または新しいStaticPagedList(products、page、PageSize、count * pagesize);
したがって、使用可能なすべてのカウントをページで提供します。