Silverlight 3.0 içerisinde DataPager ve istemci/sunucu taraflı sayfalama

0 dakikada yazıldı

7001 defa okundu

Düzenle

Sayfalama senaryoları her zaman ihtiyacımız olan işlevselliklerden
olmuştur. En basit kullanımı ile bir DataGrid içerisindeki verinin
sayfalanabilir olarak gösterilebilmesi gerekir. Bu sayfalama işlemi
bazen sunucu taraflı bazen de istemci taraflı yapılabilir. Bu makalede
Silverlight 3.0 ile beraber gelen DataGrid kontrolünü kullanarak
sayfalama işlemlerine göz atacağız.

Sayfalama için görsel kontrol?

Sayfalama işlemi için doğrudan Silverlight 3.0 ile beraber gelen
DataPager kontrolünü kullanacağız. Bu kontrol kendisine verilen
PagedCollectionView nesnesine göre sayfalama yapabiliyor. Tabi söz
konusu veriyi doğrudan DataPager'a vermek pek anlamlı değil o nedenle
verimizi yaratıp ilk olarak bir gride bağlayalım. Sonrasında Grid
içerisindeki veriyi sayfalaması üzerine DataPager'a gerekli komutu
vereceğiz.

İstemci taraflı sayfalama...

İlk örneğimizde tüm veriyi istemci tarafında sayfalayacağız. Bu gibi bir
sayfalamayı ancak tüm veriyi istemci tarafına uygun bir sürede
alabiliyorsanız yapabilirsiniz. Eğer elinizdeki veri bir defada
istemciye yüklenemeyecek durumda ise sayfalamayı da tabi ki sunucu
tarafında yapmak gerekecektir. İstemci tarafındaki sayfalama aslında
sadece görsel amaçlarla ve ileriki adımlarda filtreme için
kullanılabilir.

[XAML]

<UserControl
xmlns
:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"

       xmlns:layoutToolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit"

       xmlns:dataControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm"

       x:Class="SilverlightApplication77.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400"
Height
="300">

    <Grid
x
:Name="LayoutRoot"
Background
="White">

        <StackPanel>

            <data:DataGrid
x
:Name="Grid"></data:DataGrid>

            <dataControls:DataPager
x
:Name="Pager"></dataControls:DataPager>

        </StackPanel>

    </Grid>

</UserControl>

Yukarıdaki örneğimizde bir DataGrid ve bir de DataPager kontrolü
bulunuyor. Söz konusu kontrollere gerekli isimleri de vererek kod
tarafından ulaşılabilir hale getirip uygulamamıza devam edebiliriz.
Elimizde basit bir isim listesi olduğunu düşünürsek ilk olarak bu
listeyi bir PagedCollectionView'a çevirmemiz gerekecek.

[VB]

    Private Sub MainPage_Loaded(ByVal sender As Object,
ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

        Dim AnaListe As New
List(Of String)

        AnaListe.Add("Daron")

        AnaListe.Add("Burak")

        AnaListe.Add("Muammer")

        AnaListe.Add("Uğur")

        Dim Liste As New
PagedCollectionView(AnaListe)

 

        Grid.ItemsSource = Liste

    End Sub

Yukarıdaki kod içerisinde basit bir String List'in
PagedcollectionView'a çevrilmesini görebilirsiniz. Aslında işlem
epey basit çünkü PagedCollectionView zaten constructor'larından birinde
IEnumarable interface'ini implemente eden obje istiyor. Elimizdeki
liste de buna uyduğunu göre doğrudan çeviri işlemini hızlıca
halledebiliyoruz. Son olarak eldeki PagedCollectionView'u da Grid
adındaki DataGrid'imize aktarmamız ilk aşamanın tamamlanması için
yeterli olacaktır.

[XAML]

<UserControl
xmlns
:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"

       xmlns:layoutToolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit"

       xmlns:dataControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm"

       x:Class="SilverlightApplication77.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400"
Height
="300">

    <Grid
x
:Name="LayoutRoot"
Background
="White">

        <StackPanel>

            <data:DataGrid
x
:Name="Grid"></data:DataGrid>

            <dataControls:DataPager
x
:Name="Pager"
PageSize
="2" DisplayMode="PreviousNextNumeric"

                   Source="{Binding
ItemsSource
, ElementName=Grid}"></dataControls:DataPager>

        </StackPanel>

    </Grid>

</UserControl>

Şu ana kadar DataPager kontrolümüz ile DataGrid'in birbirinden haberi
yoktu. İşte yukarıdaki kod içerisinde bu iki kontrolü birbirinden
haberdar ediyoruz ve DataGrid'in ItemsSource'un kodumuz ile vermiş
olduğumuz PagedViewCollection'ın DataPager tarafından kontrol edilmesini
sağlıyoruz.

Tüm bu işlemleri yapabilmek için basit bir Element Binding kullanarak
DataPager'ın Source Property'sini Grid'in
ItemsSource'una bind etmemiz yeterli oluyor. Artık elimizde istemci
tarafında sayfalama ile çalışabilen bir DataGrid var. DataGrid'in her
sayfasında kaç kayıt gösterileceğini PageSize özelliğinden
ayarlayabilirsiniz.

Sayfalama desteği ile bir DataGrid kontrolü.
Sayfalama desteği ile bir DataGrid kontrolü.

DataPager ile ilgili farklı görsel özellikler için DisplayMode
Enumaration'ını incelemenizi tavsiye ederim.

Sunucu taraflı sayfalama...

Eğer veri miktarınız çok yüksek ise maalesef tüm veriyi istemci tarafına
almak gibi bir şansınız olmayabilir. Bu gibi durumlarda Silverlight
uygulamasının sürekli olarak istediği sayfanın sayısını sunucuya
göndererek sadece o sayfadaki veriyi sunucudan alması gerekecektir.
Tahmin edebileceğiniz üzere bu işin iki farklı ayağı var; birincisi
sunucu tarafında uygun sayfaya ait veriyi sayfa numarasına göre
döndürebilen bir web servisinin hazırlanması, ikincisi ise bu servisin
Silverlight tarafından doğru olarak kullanılabilmesi.

[Service / VB]

    Dim DB As New
DataClasses1DataContext

 

    <OperationContract()> _

    Public Function VeriGetir(ByVal Atla As Integer, ByVal Al As Integer) As List(Of
Urunler)

        Return (From inc In DB.Urunlers Skip (Atla) Take (Al) Select inc).ToList()

    End Function

 

    <OperationContract()> _

    Public Function KayitSayisi() As Integer

        Return (From inc In DB.Urunlers Select inc).Count

    End Function

Yukarıda sunucu tarafındaki servisimizin kodunu bulabilirsiniz. Toplamda
iki servise ihtiyacımız var; bu servislerinden biri veritabanında
bulunan toplam kayıt sayısını alarak istemciye göndermek zorunda.
Böylece DataPager kontrolü toplam kaç sayfalık bir veri ile uğraştığını
bilebilecek. Diğer yandan sayfa sayfa duruma göre veri döndürebilecek
bir servis de kesinlikle şart. Tüm bunları LINQ2SQL ile beraber
yaparsanız sayfalamanız otomatik olarak SQL tarafına kadar taşınmış
oluyor. Aksi halde sizin SQL tarafındaki sayfalama mekanizmasını da
kurmanız gerekecektir.

Özellikle VeriGetir adındaki metodumuzu incelemek gerekirse toplamda iki
parametre aldığını görebiliriz. Bunlardan biri veritabanından kayıt
çekilirken kaç kayıt atlanmasını gerektiğini diğeri ise kaç kayıt
alınması gerektiğini belirtiyor. Örneğin her defasında 10'ar kayıt
gösteriyorsak ve üçüncü sayfadaysak toplam 20 kayıt atlamamız gerektiği
ve 10 kayıt almamız gerektiğini hesaplamak pek zor değil. Bu
hesaplamaları Silverlight tarafında yaparak servise parametre olarak
vereceğiz. Servis de bize uygun veriyi döndürecek.

[XAML]

<UserControl
xmlns
:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"

       xmlns:layoutToolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit"

       xmlns:dataControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm"

       x:Class="SilverlightApplication77.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400"
Height
="300">

    <Grid
x
:Name="LayoutRoot"
Background
="White">

        <StackPanel>

            <data:DataGrid
x
:Name="Grid"></data:DataGrid>

            <dataControls:DataPager
x
:Name="Pager"
PageSize
="1" DisplayMode="PreviousNextNumeric"></dataControls:DataPager>

        </StackPanel>

    </Grid>

</UserControl>

Yukarıdaki XAML kodu uygulamamızın ana ekranını temsil ediyor. Bir
önceki örneğimizden farklı olarak burada artık bir ElementBinding
kullanmadığımı görebilirsiniz. Nedeni çok basit; artık tüm veri DataGrid
üzerinde değil o nedenle DataPager gidip de Grid'in ItemsSource'u
üzerinden sayfalama yapamayacak.

Not: ElementBinding mekanizmasının
çalışmasını ve ilk örneğimizdeki sistemi daha profesyonel bir şekilde
veriyi sunucu tarafında sayfalar hale getirmek isterseniz yapmanız
gereken
IPagedCollectionView interface'ini implemente eden kendi
PagedCollectionView nesnenizi programlamanız. Nesne içerisinde sayfa
değişim eventlarından bir çok farklı duruma erişip verinin uygun
kaynaklardan alınmasını sağlayabilirsiniz. Ben kişisel olarak ne kadar
bu yolun daha profesyonel olduğunu düşünsem de hem yazılım geliştirme
süreci olacak hem de kalifikasyon açısından hedeflediğimiz işlevsellik
için biraz yüksek seviyede kaldığını düşünüyorum. O nedenle makalede çok
daha basit bir teknik kullanacağım. Eğer siz daha karışık
işlevselliklere ihtiyaç duyarsanız
IPagedCollectionView
interface'i üzerinden ilerleyebilirsiniz.

DataPager'ı kullanmaktaki tek amacımız kullanıcıya uygun arayüzü
göstermesi. Yani "sağ" "sol" düğmeleri ve "sayılar" bizim için yeterli.
Bundan sonrasında ne de olsa sunucu tarafında sayfalama yapacağımıza
göre DataPager'ın bize kullanıcı tarafından seçili sayfanın sayısını
vermesi yeterli olacaktır. Fakat DataPager'ın çalışması için uygun bir
PagedViewCollection'ın Source olarak atanmış olması şart.

[VB]

    WithEvents Servis As New
ServiceReference1.Service1Client

 

    Private Sub MainPage_Loaded(ByVal sender As Object,
ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

        Servis.KayitSayisiAsync()

    End Sub

 

    Private Sub Servis_KayitSayisiCompleted(ByVal sender As Object,
ByVal e As
ServiceReference1.KayitSayisiCompletedEventArgs) Handles Servis.KayitSayisiCompleted

        Dim Liste As New
List(Of Nullable(Of Integer))

        For index As Integer
= 1 To e.Result

            Liste.Add(Nothing)

        Next

        Dim DummyList As New
PagedCollectionView(Liste)

        Pager.Source = DummyList

 

        Servis.VeriGetirAsync(Pager.PageIndex * Pager.PageSize,
Pager.PageSize)

    End Sub

Sayfa ilk yüklendiğinde hemen kayıt sayısını getirecek olan servisimizi
çağırıyoruz. Söz konusu servisten toplam kayıt sayısı geldiği gibi
sadece DataPager'a verilmek üzere boş bir List yaratıyoruz. Bu List
içerisinde Item sayısı gelen kayıt sayısı ile aynı fakat List'in
içindeki her Item aslında boş! DataPager'ın çalışması için aslında boş
bir liste yaratıp kendisini kandırıyoruz.

[VB]

    Private Sub Pager_PageIndexChanged(ByVal sender As Object,
ByVal e As System.EventArgs) Handles Pager.PageIndexChanged

        Servis.VeriGetirAsync(Pager.PageIndex * Pager.PageSize,
Pager.PageSize)

    End Sub

 

    Private Sub Servis_VeriGetirCompleted(ByVal sender As Object,
ByVal e As
ServiceReference1.VeriGetirCompletedEventArgs) Handles Servis.VeriGetirCompleted

        Grid.ItemsSource = e.Result

    End Sub

Artık DataPager kontrolümüzün PageIndexChanged durumunu yakalayabiliriz.
Her defasında sayfa değiştiğinde sayfa sayısı ile sayfa boyutunu çarpıp
atlanacak olan kayıt sayısını buluyoruz. Zaten sayfa sayısı Index olarak
geldiği için ilk sayfada 0 gelecek ve atlanacak kayıt sayısı da 0
olacak. Servise göndermemiz gereken ikinci parametre de zaten
DataPager'ın PageSize özelliği, yani sayfa başına gösterilecek kayıt
sayısı.

Son olarak bu servisimizden gelen sonucu da Grid'imize bağlarsak işlem
tamamlanmış olacaktır. Artık elimizde sunucu tarafında sayfalama
yapabilen bir arayüzümüz var.