PagedList kullanarak verileri sayfalama

Verileri sayfalamak iyidir :D Giriş için cümle bulamıyorum resmen, neyse siz girdik sayın :)

Sağa sola bulaşmadan Nuget Gallery den PagedList.Mvc paketini projemize ekliyoruz. Nasıl ekliyoruz sorusunun cevabını burada bulabilirsiniz. PagedList açık kaynak bir proje, github sayfasına buradan ulaşabilirsiniz.


PagedList’ in kullanımı oldukça basit. Örneğimize göz atalım;

        public ViewResult Index(int? page)
        {
            int pageIndex = page ?? 0;
            var result = db.mesajs.OrderByDescending(x=>x.id).ToPagedList(pageIndex, 2);
            return View(result);
        }

View katmanına verileri gönderdiğimiz Action kontrolümüzde sadece şu kontrolü yapıyoruz. Eğer sayfa numarası yoksa sayfa numarasını 0 (sıfır) a eşitliyoruz. Sonrasında ToPagedList içerisine olduğumuz sayfayı ve bir sayfada listelenecek kayıt sayısını belirtip view a gönderiyoruz. View’ ımız yani kullanıcıların gördüğü kısımı ise aşağıda ki şekilde düzenliyoruz. Aşağıda tüm sayfalama şekillerini gerçekleştirdim, siz istediğinizi kullanabilirsiniz.

@model PagedList.IPagedList<mvcPagedList.Models.mesaj>
@using PagedList.Mvc;
@using PagedList;

@{
    ViewBag.Title = "Index";
}

<style type="text/css">
    h3{margin-bottom:5px}
    .PagedList-pager{}
    .PagedList-pager ul{list-style:none;margin:0;padding:0}
    .PagedList-pager ul li{margin:0;padding:0;float:left;margin-right:10px}
    .t{clear:both}
</style>

<h2>Kayıtlar</h2>

<table>
    <tr>
        <th>
            baslik
        </th>
        <th>
            icerik
        </th>
    </tr>

@foreach (var item in Model)
{
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.baslik)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.icerik)
        </td>
    </tr>
}

</table>

<hr />

<h3>Varsayılan sayfalama</h3>
@Html.PagedListPager(Model, page => Url.Action("Index", new { page = page }))
<div class="t"></div>

<h3>Önceki, Sonraki</h3>
@Html.PagedListPager(Model, page => Url.Action("Index", new { page = page }), PagedListRenderOptions.Minimal)
<div class="t"></div>

<h3>Önceki, Sonraki ve hangi sayfadasınız</h3>
@Html.PagedListPager(Model, page => Url.Action("Index", new { page = page }), PagedListRenderOptions.MinimalWithPageCountText)
<div class="t"></div>

<h3>Önceki, Sonraki ve hangi sayfadasınız. Toplam kayıt sayısı</h3>
@Html.PagedListPager(Model, page => Url.Action("Index", new { page = page }), PagedListRenderOptions.MinimalWithItemCountText)
<div class="t"></div>

<h3>Sayfa numaraları</h3>
@Html.PagedListPager(Model, page => Url.Action("Index", new { page = page }), PagedListRenderOptions.PageNumbersOnly)
<div class="t"></div>

<h3>Önceki, sonraki ve sayfa numaraları</h3>
@Html.PagedListPager(Model, page => Url.Action("Index", new { page = page + 1 }), PagedListRenderOptions.OnlyShowFivePagesAtATime)
<div class="t"></div>


<h3>Kişiselleştirilmiş sayfalama</h3>
@Html.PagedListPager(Model, page => Url.Action("Index", new { page = page }), new PagedListRenderOptions { LinkToFirstPageFormat = "<< İlk", LinkToPreviousPageFormat = "< Önceki", LinkToNextPageFormat = "Sonraki >", LinkToLastPageFormat = "Son >>" })

Bu sayfalama yöntemi webForm’ daki GridView ve benzeri diğeri kontroller içerisindeki veriyi sayfalamaktan çok daha performanslı. Sebebi ise şu, bu kontrollerin bize sunduğu sayfalama yöntemlerinde, ilk önce veritabanındaki tüm kayıtlar kontrolün içine doldurulup sonra sayfalanıyor. Yani 10000 satırlık bir verimiz varsa önce tüm veri çekileceğinden, ciddi bir performans kaybı oluşacaktır. Bu yöntemde sayfalama işlemini Sql Server Profiler ile gözlemlediğimizde, sadece istediğimiz kayıtların geldiğini gözlemye biliyoruz.

Yukarıda ki durum sayfamızın ilk yüklendiğinde neler olduğunu gösteriyor. 1. kısım olarak işaretli yerde veritabanında ki toplam kayıt sayısı alınıyor, 2. kısımda 0 dan büyük 2 kayıt isteniyor, neden 2 kayıt çünkü biz ToPagedList içerisine gönderdiğimiz parametrede 1 sayfada 2 kayıt olmasını istemiştik ;) Neden 0 çünkü eğer sayfa numarası yoksa 0 a eşitlemiştik ;) Bu olay mysql de limit fonksiyonu ile yapılabiliyor. Limit olayını Linq de ki Take() Skip() fonksiyonlarını kullanarak yapabiliyoruz. PagedList’ in temelinide bu ikili oluşturuyor ;)


İlk sayfaya geçtiğimizde yukarıdaki durumu gözlemliyoruz. Değişen tek şey 0 dan büyük 2 kayıt yerine bu sefer 2 den büyük 2 kayıtın istenmesi. Diğer sayfalara geçtğimizde de 2′ nin katları şeklinde arttığını görüyoruz, yani her seferinde 2 kaydı bize çağırıyor ;) Anlatacaklarım bu kadar, umarım faydalı olmuştur.

Projenin çalışır halini şuradan görebilirsiniz, buradan indirebilirsiniz.

  • Tansu Özmen

    Ellerine sağlık Abdullah, her zamanki gibi çok iyi bir makale. Başarılarının devamını dilerim :)

    • apoStyLEE

      Çok teşekkür ederim abi :)

  • Recai cansız

    Teşekkürler Abdullah bey..

  • Ferat

    Harika :D elinize sağlık.. birde autocomplateextender bekliyoruz mvc için :D

  • Ferat

    perf. yazılarını görmemişim.. tam test edecektimki :D fark ettim :D hayy Allah razı olsun ramazan ramazan :D

  • Ferat

    herşey çok güzel de PagedList.Mvc bir türlü kurulmuyor. işlevler çalışıyor ama, sayfaların linklerini yazamadım bu yüzden…

  • Ferat

    sizin dll leri ekledim mecburen. günceli inmedi!
    yanlız aktif olana css yazmak istedim. nasıl yapılabilir…

  • Ferat

    html desteği de yok malesef :) çokmu oldum ben ya

  • apoStyLEE

    Sanırım biraz geç bir cevap oldu :S
    Örnek projeyi indirip incelerseniz orada istediklerinizin olduğunu göreceksiniz. Html desteği yok derken tam olarak neyi kastettiğinizi anlamadım ? Eğer biçimlendirmeyle ilgiliyse bu işi css ile istediğiniz gibi düzenleyebilirsiniz ;)

  • Ahmet

    :)))) muthis bir giristen sonra guzel bir yazi olmus:) eline saglik;)

  • Ferat

    evet hocam ben buna baya bir evrim yaptım lakin aşamadığım nokta aktif olayı yani sayfa aktif iken o ul de bir css atmam lazm ama yok malesef özellik

    • apoStyLEE

      aktif olan sayfaya PagedList-currentPage adında bir sınıf (class) atanıyor. Bu sınıfı biçimlendirebilirsiniz. Örneğin .PagedList-currentPage{color:red!important} gibi..

  • Ferat

    eyv. usta şimdi oldu işte…

    • Berat İnceçam

      abi butun yorumlar sılınmıs aynı hatayı bende alıyotum bi soyleyebilirseniz iyi olur

  • hakan

    yazı için teşekkür ederim ama bir yerde takıldım, sizin örneğinizde sorunsuz olarak çalışıyor ama ben
    sayfa sayısını yazdırmak için gerekli olan @Html.PagedListPager(Model, page => Url.Action(“Index”, new { page = page })) kısmını view a eklediğimde aşağıdaki hatayı alıyorum. sebebi ne olabilir acaba ?

    Compiler Error Message: CS1928: ‘System.Web.Mvc.HtmlHelper<System.Collections.Generic.IEnumerable>’ does not contain a definition for ‘PagedListPager’ and the best extension method overload ‘PagedList.Mvc.HtmlHelper.PagedListPager(System.Web.Mvc.HtmlHelper, PagedList.IPagedList, System.Func)’ has some invalid arguments

    • Berat İnceçam

      abi butun yorumlar sılınmıs aynı hatayı bende alıyotum bi soyleyebilirseniz iyi olur.

  • talat

    Compiler Error Message: CS1928: ‘System.Web.Mvc.HtmlHelper’ does not contain a definition for ‘PagedListPager’ and the best extension method overload ‘PagedList.Mvc.HtmlHelper.PagedListPager(System.Web.Mvc.HtmlHelper, PagedList.IPagedList, System.Func)’ has some invalid arguments bu hatayı nasıl aşabilirim?

  • melih

    int pageIndex = page ?? 0;
    Sıfır verdiğinde çalışmıyor kod aşağıdaki hatayı veriyor

    PageNumber cannot be below 1.
    Parameter name: pageNumber
    Actual value was 0.