Ana Sayfa | English Blog | Seminer TV | Dil Cookie Sil  Blog'u Mail ile takip et!       
Daron Yöndem - July, 2009
bir yazılımcının tasarıları...
 Friday, July 31, 2009

Son 3 gündür Ankara'dayım. Peki neden? Microsoft Yaz Okulu başladı da ondan :) Üç gündür yaz okulundaki arkadaşlarla Silverlight 3'ün altından girdik üstünden çıkmaya çalıştık diyebilirim :) Araya biraz tabi LINQ attık sonra bu kadar XAML görmüşken WPF'e de bakmamak olmazdı. Hatta son anda ben gaza gelip Dynamic Data bile gösterdim :) (Evet bazılarınız kaçmıştı)

Microsoft Yaz Okulu / Ankara
Microsoft Yaz Okulu / Ankara

Üç günlük güzel bir maraton oldu diye tahmin ediyorum. Üç günün sonunda öğrencilerimden pek yorum koparamamış olsam da :) en azından anlattıklarımı önümüzdeki üç günde tekrar etmezlerse unutacaklarnın farkındalar :) hadi bakiyim hafta sonu da bir üzerinden geçin konuların!

Şaka bir yana çok eğlenceli ve bir o kadar da disiplinli ve öğrenmeye istekli bir sınıf vardı karşımda. Bu kapsam özel bir sınıf olduklarını dile getirmem sanırım yanlış olmaz. Tabi daha bu seneki İstanbul ve İzmir ekiplerini görmedim :) onları da yakında göreceğim bakalım. Özellikle proje haftasında hangi gruplar neler çıkaracak heyecanla bekliyorum.

Tüm sınıf kod yazıyor!
Tüm sınıf kod yazıyor!

Üç gün boyunca benimle beraber koşan hepinize çok teşekkürler. Her öğle yemeğinde benimle beraber (artık isteyerek mi mecburen mi bilemiyorum) mantı yediğiniz için ayrıca teşekkürler :D ama bu kadar çok mantı yemeyin yoksa sonunuz benden farklı olmaz :D En kısa zamanda tekrar görüşmek üzere!

Friday, July 31, 2009 12:22:12 PM (GTB Standard Time, UTC+02:00)  #    Comments [10]    | 
 Thursday, July 30, 2009

Bugünlerde Ankara'dayım :) Neden olduğu sanırım yarınki postum daha net anlatacaktır. Hazır Ankara'dayken mailgrup olarak uzun süredir hayalini kurduğumuz Ankara buluşmamızı da yapalım dedik. Hafta içi olması eminim ki çoğu arkadaşımızın canını sıkmıştır fakat maalesef şimdilik başka şans yok gibiydi. Hızlı bir organizasyonla Kızılay'da buluşup sonra da Kocatepe tarafında çay içerek geceyi noktaladık :)

Mailgrup Ankara Buluşması
Mailgrup Ankara Buluşması

Gerçekten hoş bir sohbet ortamı oluştu diyebilirim. Minik bir grup da olsak :) iş hayatından arkadaşlarla öğrenci arkadaşlarımızın karşı karşıya sohbet edebilmesi de bence güzel oldu. Böylece gençler de kabaca kendilerini ileride nelerin beklediğini görmüş oldular belki :) Katılan herkese teşekkür ediyorum, kamışlı limonata rocks! diyerek yazımı bitiyorum :D

Not: Bu arada uzun zamandır bakmıyordum bizim mail grup 300 kişiyi geçmiş :) Sabırlı grubu takip edenleri de kutluyorum :) Outlook kullanıp gruba özel kural/klasör yaratmayı unutmayın günde 100 maili geçebiliyor bazen :) Merak edenler için grubun adresi : http://daronyondem.groups.live.com/

Thursday, July 30, 2009 12:07:53 PM (GTB Standard Time, UTC+02:00)  #    Comments [3]    | 
 Wednesday, July 15, 2009

Uzun süre oldu :) Bu sürede onlarca mail aldım. İlk olarak hepinize ilginiz için çok teşekkür ediyorum. Biliyorum geciktim, fakat eksikler vardı ve toparlamam gerekti. Neden mi bahsediyorum? Tabi ki "Silverlight 3.0 Öğrenme Ayı" webinerlerinin kayıtlarından bahsediyorum. Biliyorsunuz kayıtların üçü başarısız olmuştu, sonrasında aynı webinerleri tekrar offline'da kaydetmem gerekti. Buna bir de encoding süreçleri eklenenince herşeyip derlenip toparlanması epey uzun sürdü. Fakat sonunda herşey hazır!

15 Saatlik Silverlight 3.0 Eğitimi

Bir de baktım ki toplam 15 saati bulmuş. Sanırım güzel bir eğitim seti oldu. Özellikle baştan sonra doğru izlerseniz daha da faydalı olacağını düşünüyorum çünkü konuların her biri birini takip ediyor. Tabi unutmayın ki tüm webinerler Silverlight 3.0 Beta ile yapıldı o nedenle buradaki makaleyi incelemeyi de unutmayın.

Hepsi sizi bekliyor! Download linkleri için hemen SeminerTV'yi ziyaret edin!

Not: Eğitim setini her yerde çekinmeden duyurabilirsiniz hatta doğrudan download linklerini de gönül rahatlığı ile paylaşabilirsiniz! Bilgi paylaşımı için... İleri! :)

Tuesday, July 14, 2009 11:28:35 PM (GTB Standard Time, UTC+02:00)  #    Comments [23]   Silverlight 3.0  | 
 Sunday, July 12, 2009

Dün "Windows 7 ile 7 Saat" etkinliğimizi gerçekleştirdik. Benim için süper keyifli ve güzel bir gündü. İlk defa bir INETA etkinliğinde ITPro tarafına da hitap ettik. İki salonda paralel oturumlar ile hem IT'cilere hem de yazılım geliştiricilere özel oturumlarımız oldu. Amacımız yazılımcılara IT ekiplerini de biraz yan yana getirmekti fakat maalesef olmadı :) Neden mi?

İlk olarak tahmin ettiğimizin çok üstünde bir katılım oldu. Yaklaşık 2 katı diyebilirim :) Salonlara dışarıdan sandalye toplama çabaları için binanın güvenlik görevlilerini büyük bir teşekkür borçluyum. Katılım bu şekilde artınca maalesef yemek aramızı da ayrı zamanlarda vermek zorunda kaldık çünkü herkesin aynı anda yemek yiyebileceği kadar büyük bir alan bulma şansımız yoktu.

Windows 7 ile 7 saat!
Windows 7 ile 7 saat!

Etkinlikteki konular zaten beni heyecanlandıran konulardı, kişisel olarak demolarım çatlamadığı için çok mutluyum :) Üç oturumumun ikisi donanıma bağımlıydı, Multitouch ve Sensör API'ları ve donanımlar beni zor durumda bırakmadan günü bitirdim. Gün boyunca en neşeli anlardan biri yan salonda ITPro ekibindeki konuşmacımız Muammer Benzeş'in sesinin bir anda bizim salondaki hoparlörlerden de gelmesi oldu :) Tam da o anda Muammer "Biz yazılımcılarından daha kalabalığız bakın!" gibi sözler edince :) neredeyse salonlar arası bir savaş başlatacaktı :)

Günün sonunda Windows 7'ye ücretsiz upgrade'li Vista'mızı da hediye ederek iyisi ile kötüsü ile güzel bir gün geçirdik diye tahmin ediyorum. Katılan herkese ÇOK teşekkürler. Başka bir etkinlikte tekrar görüşmek üzere.

Not:Etkinliklteki tüm fotoğrafları paylaşacağız. Bu yazımın yorumlarını takip ederseniz yorumlarda fotoğrafları çeken arkadaşların linklerini bulabileceksiniz.

Sunday, July 12, 2009 7:38:11 PM (GTB Standard Time, UTC+02:00)  #    Comments [17]   Windows 7  | 
 Saturday, July 11, 2009

Heyecanle beklenen an geldi ve Silverlight 3 yayınlandı. Beta sürümünden Release'e kadar olan değişikliklere göz atacağımız bu yazıda önce gelin Silverlight 3 dünyasına hızlıca nasıl gireriz bir göz atalım.

http://www.silverlight.net/getstarted

Silverlight dünyasına girmenin en kolay yolu hemen yukarıdaki adresi ziyaret etmek. Bu adres içerisinde Silverlight 3 tarafında bilgisayarınıza yüklemeniz gereken herşeyi bulabilirsiniz. Unutmadan, eğer bilgisayarınızda Silverlight 3 Beta yüklemeleri varsa herşeyin öncesinde bu yüklemeleri bilgisayarınızdan kaldırmayı unutmayın.

Silverlight 3.0 Yüklemeleri
Silverlight 3.0 Yüklemeleri

Yukarıdaki ekran görüntüsünde silverlight.net sitesinin bir parçasını görüyorsunuz. Burada ilk aşamada yer alan yüklemelere özellikle dikkat etmek gerek. "Web Platform Installer" olarak geçen yükleme paketi bilgisayarınız için gerekli tüm yüklemeleri yapabilir. Bu yüklemeler içerisinde Visual Studio'nun Express sürümü ve SQL Express de dahil. WPI ile ilgili ayrı bir yazı yazılabilir fakat şimdilik kabaca genel anlamına değinmek yeterli olacaktır diye tahmin ediyorum. WPI'ın amacı bilgisayarınıza tüm yazılım geliştirme platformunu yüklemektir. Yükleme esnasından ASP.NET MVC'den PHP modüllerine kadar istediklerinizi seçebilirsiniz.

Eğer bilgisayarınızda hali hazırda Visual Studio yüklü ise be zaten "benim platformum hazır" diyorsanız bu sefer hızlıca "download the tools directly" linkine tıklayıp Visual Studio Tools for Silverlight paketini indirebilirsiniz. Böylece yazılım geliştirme ortamınız Silverlight 3.0 ile tanışmış olacaktır.

Expression Blend 3 RC

Silverlight 3.0 ile beraber tabi ki yeni bir de Blend sürümüne ihtiyacımız var. Expression Studio 3 daha yayınlanmadığı için Silverlight 3.0'a özel olarak Expression Blend 3'ün RC sürümü Silverlight'cılarla paylaşıldı. Çok yakın zamanda Expression Studio 3 ile beraber Blend 3 de release olacak. Şimdilik RC sürümü ile dahatlıkla idare edebilirsiniz. Sketchflow kısmı eminim ki dikkatinizi çekecektir. Bu konuda uzun uzun makale ve seminer planlarım var :)

Silverlight Toolkit ve DeepZoom tarafında da yeni gelişmeler var. İndirip yeni sürümlerini ücretsiz olarak bilgisayarınıza kurabilirsiniz. Özellikle DeepZoom Composer tarafında yeni menü navigasyon sistemlerini incelemenizi tavsiye ederim. Ayrı makaleler bu konuda da çok yakında karşınızda olacak.

Silverlight 3.0 RTW ile değişenler?

En büyük değişikliklerden biri Silverlight 3.0 SDK içerisinde yer alan bazı kontrollerin doğrudan Toolkit içine taşınmış olması. Bu duruma çok farklı yorumlar getirmek mümkün fakat esas yapılmak istenen şey bu kontrolleri SDK içerisine eklemeden önce biraz daha feedback almak ve bu süreçte de kontrolleri açık kaynak kodları ile beraber yazılım geliştiriciler ile paylaşabilmek. O nedenle aşağıdaki kontrollerin hepsi Beta SDK içerisinden Toolkit tarafına kaydırıldı.

DockPanel, WrapPanel, Expander, HeaderedContentControl, Viewbox,
DataForm, ExpandDirection, ExpanderAutomationPeer, LengthConverter, StretchDirection

DataForm ve DataPager

DataForm ve DataPager kontrollerinde büyük değişiklikler oldu. Artık DataForm kontrolünün Fields adında bir collection'ı yok. Onun yerine eskiden de olan Edit ve Normal modlar için özeleştirme sağlayan Template yapıları kullanılacak. Eski Template yapılarında tasarımı sıfırdan yaratırken bu sefer Template'ler içerisinde IPagedCollectionView adında kontroller de kullanabileceğiz. Söz konusu DataField'ler içerisine kendi kontrollerini koyarak özelleştirmeler yapabilirsiniz. Açıkçası bu değişiklik benim çok hoşuma gitmedi. Eskisi özellikle DataGrid ile çok daha uyumlu bir yazılımcı deneyimi sağlıyordu. Fakat özünde bu değişikliklerin tekrar değişmesi de olası, çünkü ne de olsa bu kontroller Toolkit içerisinde.

DataPager kontrolü tarafında ise IPagedCollectionView sınırlaması kaldırılarak artık herhangi bir IEnumerable kullanılabilmesi sağlanmış.

MetaAttributes

Özellikle DataForm içerisinde Fields Collection'ın kaldırılması sonrasında canım biraz sıkılmıştı ki MetaAttributes tarafındaki değişiklikler keyfimi yine getirdi. Genelde ister DataGrid olsun ister DataForm, bizim Fields veya Columns collectionları editlememizin esas nedeni bir kolonu göstermek istemememizden veya editlenmesini istememizden kaynaklanır. AutoGenereateColumns/Fields özelliklerini sevsek de kolon başına ayar yapabilmek için Field'leri elle yaratmamız gerekiyordu.

[VB]

    <Bindable(True, BindingDirection.TwoWay)> _

    Private _Ornek As String

    Public Property Ornek() As String

        Get

            Return _Ornek

        End Get

        Set(ByVal value As String)

            _Ornek = value

        End Set

    End Property

Eskiden uygulayabildiğimiz yukarıdaki teknik ile bir Property'nin Bindable olup olmadığını hatta ne şekilde Bind edilebileceğini de ayarlayabiliyorduk. Yeni SL 3.0 RTW ile bu MetaAttribute'ler biraz değişti.

[VB]

    <Display(AutoGenerateField:=True)> _

    <Editable(False)> _

    Private _Ornek As String

    Public Property Ornek() As String

        Get

            Return _Ornek

        End Get

        Set(ByVal value As String)

            _Ornek = value

        End Set

    End Property

Artık çok daha kolay bir şekilde doğrudan bir Property'nin AutoGenerateField aşamasında yaratılıp yaratılmayacağını belirleyebiliyor veya Editable ile bu özelliğini editlenebilir olup olmadığı bilgisini de aktarabiliyoruz. Bunun gibi yaratılacak olan kolonun kaçıncı sırada olacağını veya kolon adını da aşağıdaki şekilde belirtebilirsiniz.

[VB]

    <Display(AutoGenerateField:=True, Name:="Kolon Adı", Order:=1)> _

    <Editable(False)> _

    Private _Ornek As String ....

Navigation Framework

Silverlight 3.0 Beta ile karşılaştığımız Navigation Framework içerisinde de ciddi değişiklikler var. Eski halinde UriMapper'ımızı App.XAML içerisinde yaratmak zorunda olup bir de bunun üzerine yarattığımız Mapper sınıfının instance'ına ait ismin de uriMapper olmak zorunda olması ciddi anlamda saçmalıktı :) Tabi ki bu durum düzeltilmiş ve artık uriMapper'larınızı UserControl içerisinde de yaratabiliyor ve istediğiniz ismi verebiliyorsunuz. Sonrasında da uriMapper'ı elle istediğiniz bir frame'e bağlamanız gerekiyor.

[XAML]

....

    <UserControl.Resources>

        <navigationCore:UriMapper x:Key="HerhangiBirMapper">

            <navigationCore:UriMapping Uri="Siparis" MappedUri="/Sayfalar/Siparis.xaml" />

        </navigationCore:UriMapper>

    </UserControl.Resources>

    <Grid x:Name="LayoutRoot">

        <navigation:Frame x:Name="frame" UriMapper="{StaticResource HerhangiBirMapper}" />

    </Grid>
.....

Son olarak eskiden herhangi bir UserControl'ü de içine alabilen frame'ler artık sadece Page'den Inherit edilmiş sayfaları alabilecek.

Diğer mini değişiklikler...

PixelShader Efektleri : Eskiden Content veya Resource olarak projelere eklenebilen PS dosyaları rahatlıkla kullanılabiliyordu artık sadece Resource olarak ayarlanmış PS dosyaları PixelShader olarak kullanılabilecek.

OutOfBrowser Desktop Uygulamaları: Eskiden Detach komutu yeni sürümde Install olarak değiştirildi. Yeni komut : App.Current.Install() Aynı şekilde eski App.Current.RunningOffline da App.Current.IsRunningOutOfBrowser oldu. ExecutionStateChanged, InstallStateChanged şeklinde değiştirildi. Ayrıca OutOfBrowser uygulamaları ile ilgili yaratılan XAML kodu da tamamen değiştirilecek harici bir OutOfBrowserSettings.xml dosyasında tutulması gerekiyor.

[OutOfBrowserSettings.xml]

<OutOfBrowserSettings ShortName="Kısayol Adı" EnableGPUAcceleration="False" ShowInstallMenuItem="True">

  <OutOfBrowserSettings.Blurb>Açıklama tooltip</OutOfBrowserSettings.Blurb>

  <OutOfBrowserSettings.WindowSettings>

    <WindowSettings Title="Pencere adı" />

  </OutOfBrowserSettings.WindowSettings>

  <OutOfBrowserSettings.Icons>

    <Icon Size="16,16">1.png</Icon>

    <Icon Size="32,32">2.png</Icon>

    <Icon Size="48,48">3.png</Icon>

    <Icon Size="128,128">4.png</Icon>

  </OutOfBrowserSettings.Icons>

</OutOfBrowserSettings>

Visual Studio 2008'de Design arayüzü? Artık yok! Yanlış duymadınız :) artık Visual Studio 2008 içerisinde Silverlight XAML dosyalarını açtığınızda otomatik olarak XAML kod kısmı açılacak ve Preview kısmı olmayacak. Aslında bu kadar çok doğru bir karar çünkü design modunda "design" yapılamadığı için :) zaten pek de anlamlı olmuyordu ve gereksiz yere işleyişi yavaşlatıyordu. Visual Studio 2010'a kadar Silverlight projelerinde Visual Studio içerisinde design penceresi olmayacak.

Silverlight.js dosyasında ufak değişiklikler var. İsteyenler hemen buradan indirebilirler: http://code.msdn.microsoft.com/silverlightjs

.NET Ria Services artık Go-Live lisansına sahip. Yani sorumluluk size ait olsa da kullandığınız projeleri yayınlayabilirsiniz. Fakat bu tabi ki RIA Services'in release olduğu anlamına gelmiyor.

Eminim ki unuttuğum bir çok değişiklik veya yenilik vardır. Onları da en kısa zamanda ayrı ayrı makaleler olarak sizlerle paylaşmak üzere...

Saturday, July 11, 2009 7:03:06 PM (GTB Standard Time, UTC+02:00)  #    Comments [2]   Silverlight 3.0  | 
 Friday, July 03, 2009

Silverlight içerisinde veri validasyonu konusunda validasyon kontrollerimiz yok gibi gözükse de aslında arka planda işimize yarayabilecek ilginç bir sistem var. Bu sistemi hem tasarımcı hem de yazılımcı beraber kullanırlarsa ortaya çok güzel sonuçlar çıkabilir. Bu yazımızda nesne bazlı veri validasyonunu nasıl yapabiliriz konusuna göz atacağız.

Hemen örneğimize başlama yoluna uygulamamızın ekranına bir DataGrid koyalım. Bir sonraki adımda uygun nesneleri yaratarak bu Grid'e bağlayacağız sonrasında da Grid içerisinde hücre başına validasyon yapmaya çalışacağız.

[XAML]

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

       x:Class="SilverlightApplication81.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">

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

    </Grid>

</UserControl>

Görsel tarafı en azından şimdilik hallettiğimize göre hemen veri tarafına geçip işimizi görecek kadar örnek veri yaratalım. İlk olarak verimiz içerisinde her nesneyi tanımlayacak olan Urun sınıfını hazırlıyoruz.

[VB]

    Public Class Urun

 

        Private PAdi As String

        Public Property Adi() As String

            Get

                Return PAdi

            End Get

            Set(ByVal value As String)

                PAdi = value

            End Set

        End Property

 

        Private PSatis As Integer

        Public Property Satis() As Integer

            Get

                Return PSatis

            End Get

            Set(ByVal value As Integer)

                PSatis = value

            End Set

        End Property

 

    End Class

Göreceğiniz üzere Urun sınıfının sadece iki tane Property'si var. Bunlardan biri ürünün adını taşırken diğeri ise toplam satış rakamını taşıyacak. Bu sınıfımızdan bir liste yaratarak rastgele urunler ekleyip Grid'imize basit bir şekilde bağlayacağız.

[VB]

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

        Dim Liste As New List(Of Urun)

        For index As Integer = 1 To 10

            Liste.Add(New Urun() With {.Adi = "Ürün Adi" & index, .Satis = Rnd() * 50})

        Next

 

        myGrid.ItemsSource = Liste

    End Sub

Bütün bu manzara içerisinde bir anda aklınızda "ürün isimleri boş bırakılmasın" şeklinde bir validasyon geldiğini varsayalım. Peki ne yapacağız? Aslında konu tahmin edeceğinizden çok daha basit. İlk olarak validasyon işlemini yapabileceğimiz basit bir yer var, orası da Urun sınıfımızın Property'lerinin Set durumu.

[VB]

       Private PAdi As String

        Public Property Adi() As String

            Get

                Return PAdi

            End Get

            Set(ByVal value As String)

                If String.IsNullOrEmpty(value) Then

                    Throw New ValidationException("isim boş geçilemez!")

                Else

                    PAdi = value

                End If

 

            End Set

        End Property

Yukarıdaki kod içerisinde sadece tek bir Property'nin set ve get durumunu görüyorsunuz. İlk baştaki örneğimizden farklı olarak Set işleminde gelen value'yu kontrol ediyoruz. Eğer Grid içerisinde bu Property'e denk gelen TextBox boş bırakılırsa doğan olarak arka tarafa grid boş değer döndürerek söz konusu nesnenin property'sini değiştirmeye çalışacak. İşte tam da o notkada devreye girip kontrolleri yapıp gerekiyorsa bir ValidationException fırlatıyoruz. Exception fırlatırken kullanıcıya vermek istediğimiz mesajı da parametre olarak constructor'a geçebiliriz.

Eğer projeyi bu hali ile Debug modunda açarsanız hatayı Debug tarafında görürsünüz. Oysa projeyi Debug mode yerine normal şekilde çalıştırırsanız aşağıdaki manzara ile karşılaşacaksınız.

Basit bir validasyon sonucu...
Basit bir validasyon sonucu...

Gördüğünüz gibi manzara gerçekten çok hoş. Görsel olarak da güzel bir animasyon ile sahneye gelen bu tooltip çoğu validasyon ihtiyacınızı giderecektir. Grid içerisinde herhangi bir ek işleme gerek kalmadan validasyonu çalışır hale getirmiş olsak da farklı kontrollerde Binding ayarlarken vermeniz gereken ek parametreler de mevcut.

[XAML]

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

       x:Class="SilverlightApplication81.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">

        <data:DataGrid x:Name="myGrid" AutoGenerateColumns="False">

            <data:DataGrid.Columns>

                <data:DataGridTemplateColumn>

                    <data:DataGridTemplateColumn.CellTemplate>

                        <DataTemplate>

                            <TextBox Text="{Binding Adi}" />

                        </DataTemplate>

                    </data:DataGridTemplateColumn.CellTemplate>

                </data:DataGridTemplateColumn>

            </data:DataGrid.Columns>

        </data:DataGrid>

    </Grid>

</UserControl>

Gridimizi yukarıdaki şekli ile biraz değiştirdik. Artık DataGrid ile beraber gelen hazır kolonları değil de özel kolon tasarımlarını kullandığımızı düşünelim. Bizim örneğimizde sadece Adi kolonunu ekledik ve bu kolonun tasarımına da bir TextBox koyduk. Böylece bu kolon sürekli TextBox olarak gözükecek. Peki acaba bu TextBox'ı da boş bıraktığımızda validasyon hatasını görebilecek miyiz? Maalesef hayır.

[XAML]

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

       x:Class="SilverlightApplication81.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">

        <data:DataGrid x:Name="myGrid" AutoGenerateColumns="False">

            <data:DataGrid.Columns>

                <data:DataGridTemplateColumn>

                    <data:DataGridTemplateColumn.CellTemplate>

                        <DataTemplate>

                            <TextBox Text="{Binding Mode=TwoWay, NotifyOnValidationError=true, Path=Adi, ValidatesOnExceptions=true}" />

                        </DataTemplate>

                    </data:DataGridTemplateColumn.CellTemplate>

                </data:DataGridTemplateColumn>

            </data:DataGrid.Columns>

        </data:DataGrid>

    </Grid>

</UserControl>

Bu noktada değiştirmemiz gereken şey Binding mekanizmamızla alakalı ayarlar. İlk olarak Mode'u TwoWay yaparak buradaki değişikliklerin de nesne tarafına yansımasını sağlıyoruz ki nesne tarafındaki validasyon gerçekleşsin. Ayrıca NotifyOnValidationError ve ValidatesOnExceptions özelliklerini de True yaparak gerekli hataların gösterilmesini sağlıyoruz.

Özel binding ile validasyon.
Özel binding ile validasyon.

Görselliği değiştirelim...

Herhangi bir kontrolün validation işlemi sonrasında InValid olması haline gösterilmek üzere InValid State'lerinin bulunması gerekir. Hali hazırda Silverlight içerisindeki çoğu kontrolde bu state'ler zaten hazır ve tasarımları yapılmış durumda. Eğer yukarıdaki örneğimizi Expression Blend ile açar ve TextBox'ın Template'ini editlemek isterseniz söz konusu menüde "Edit a copy" demeyi unutmayın.

TextBox kontolümüzü Template'ini kopyalayarak editleyelim.
TextBox kontolümüzü Template'ini kopyalayarak editleyelim.

Böylece Blend sizin yerinize standart şablonu kopyalayacaktır. Bunu yaptıktan sonra söz konusu şablonun için VisualStateManager'da InValid statelerini bulabilir ve bu stateler için hazırlanmış tasarımları değiştirebilirsiniz.

Blend içerisinde TextBox'a ait ayrı stateler...
Blend içerisinde TextBox'a ait ayrı stateler...

State'ler arası tasarımları değiştirdikten sonra büyük ihtimal ile InValid durumunde gösterilen Tooltip'in de tasarımını değiştirebilmek isteyeceksiniz. Blend içerisinden şu an için (Blend 3 MIX Preview sürümü) bir çözüm bulunmasa da kod tarafından gerekli özelleştirmeleri yapabiliriz. Textbox'ımızın Template'inden bir kopya alıp editlerken aslında beraberindeki Tooltip'in tasarımının da bir kopyası uygulamamızın sayfasında Resource olarak saklanıyor.

[XAML]

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

       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows" xmlns:System="clr-namespace:System;assembly=mscorlib" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

       x:Class="SilverlightApplication81.MainPage" Width="400" Height="300" mc:Ignorable="d">

    <UserControl.Resources>

        <ControlTemplate x:Key="ValidationToolTipTemplate">

            <Grid x:Name="Root" Margin="5,0" Opacity="0" RenderTransformOrigin="0,0">

                <vsm:VisualStateManager.VisualStateGroups>

                    <vsm:VisualStateGroup x:Name="OpenStates">

                        <vsm:VisualStateGroup.Transitions>

                            <vsm:VisualTransition GeneratedDuration="0"/>

                            <vsm:VisualTransition GeneratedDuration="0:0:0.2" To="Open">

                                <Storyboard>

                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="xform" Storyboard.TargetProperty="X">

                                        <SplineDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/>

                                    </DoubleAnimationUsingKeyFrames>

                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="Root" Storyboard.TargetProperty="Opacity">

                                        <SplineDoubleKeyFrame KeyTime="0:0:0.2" Value="1"/>

                                    </DoubleAnimationUsingKeyFrames>

                                </Storyboard>

                            </vsm:VisualTransition>

                        </vsm:VisualStateGroup.Transitions>

                        <vsm:VisualState x:Name="Closed">

                            <Storyboard>

                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="Root" Storyboard.TargetProperty="Opacity">

                                    <SplineDoubleKeyFrame KeyTime="0" Value="0"/>

                                </DoubleAnimationUsingKeyFrames>

                            </Storyboard>

                        </vsm:VisualState>

                        <vsm:VisualState x:Name="Open">

                            <Storyboard>

                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="xform" Storyboard.TargetProperty="X">

                                    <SplineDoubleKeyFrame KeyTime="0" Value="0"/>

                                </DoubleAnimationUsingKeyFrames>

                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="Root" Storyboard.TargetProperty="Opacity">

                                    <SplineDoubleKeyFrame KeyTime="0" Value="1"/>

                                </DoubleAnimationUsingKeyFrames>

                            </Storyboard>

                        </vsm:VisualState>

                    </vsm:VisualStateGroup>

                </vsm:VisualStateManager.VisualStateGroups>

                <Grid.RenderTransform>

                    <TranslateTransform x:Name="xform" X="-25"/>

                </Grid.RenderTransform>

                <Border Margin="4,4,-4,-4" Background="#152A2E31" CornerRadius="4"/>

                <Border Margin="3,3,-3,-3" Background="#252A2E31" CornerRadius="4"/>

                <Border Margin="2,2,-2,-2" Background="#352A2E31" CornerRadius="4"/>

                <Border Margin="1,1,-1,-1" Background="#452A2E31" CornerRadius="4"/>

                <Border Background="#FFDC000C" CornerRadius="4"/>

                <Border CornerRadius="4" Background="Green">

                    <TextBlock Margin="8,3,8,4" MaxWidth="250" UseLayoutRounding="false" Foreground="White" Text="{Binding Path=(Validation.Errors)[0].Exception.Message}" TextWrapping="Wrap"/>

                </Border>

            </Grid>

        </ControlTemplate>

        <Style x:Key="TextBoxStyle1" TargetType="TextBox">

            <Setter Property="BorderThickness" Value="1"/>

            <Setter Property="Background" Value="#FFFFFFFF"/>

            <Setter Property="Foreground" Value="#FF000000"/>

            <Setter Property="Padding" Value="2"/>

Yukarıdaki örnek uygulamaızın XAML kodunun ilk altmış satırını görebilirsiniz. Bu altmış satır içerisinde önemli olan şey ValidationToolTipTemplate adındaki ControlTemplate nesnesi. Söz konusu nesne TextBox'ın Template'i içerisinde de kullanılıyor. Aşağıdaki TextBox'ımızın Template'ine ait XAML kodu içerisinde yukarıdaki ControlTemplate'in nasıl kullanıldığını görebilirsiniz.

[XAML]

<Border x:Name="ValidationErrorElement" Visibility="Collapsed" BorderBrush="#FFDB000C" BorderThickness="1" CornerRadius="1">

                                <ToolTipService.ToolTip>

                                    <ToolTip x:Name="validationTooltip" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" Template="{StaticResource ValidationToolTipTemplate}" Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}">

                                        <ToolTip.Triggers>

                                            <EventTrigger RoutedEvent="Canvas.Loaded">

                                                <BeginStoryboard>

                                                    <Storyboard>

                                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="validationTooltip" Storyboard.TargetProperty="IsHitTestVisible">

                                                            <DiscreteObjectKeyFrame KeyTime="0">

                                                                <DiscreteObjectKeyFrame.Value>

                                                                    <System:Boolean>true</System:Boolean>

                                                                </DiscreteObjectKeyFrame.Value>

                                                            </DiscreteObjectKeyFrame>

                                                        </ObjectAnimationUsingKeyFrames>

                                                    </Storyboard>

                                                </BeginStoryboard>

                                            </EventTrigger>

                                        </ToolTip.Triggers>

                                    </ToolTip>

                                </ToolTipService.ToolTip>

                                <Grid Height="12" HorizontalAlignment="Right" Margin="1,-4,-4,0" VerticalAlignment="Top" Width="12" Background="Transparent">

                                    <Path Fill="#FFDC000C" Margin="1,3,0,0" Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 z"/>

                                    <Path Fill="#ffffff" Margin="1,3,0,0" Data="M 0,0 L2,0 L 8,6 L8,8"/>

                                </Grid>

                            </Border>

TextBox'ın Template'i içerisinde bulunan bir Border nesnesine Tooltip kontrolü atanmış. Söz konusu Tooltip kontrolünün şablonu ise doğrudan ValidationToolTipTemplate adındaki şablonla eşleştirilmiş durumda. Böylece biz doğrudan ValidationToolTipTemplate nesnesini değiştirerek validasyon esnasında görülen Tooltip'i değiştirebiliriz.

[XAML]

                <Border CornerRadius="4" Background="Green">

                    <TextBlock Margin="8,3,8,4" MaxWidth="250" UseLayoutRounding="false" Foreground="White" Text="{Binding Path=(Validation.Errors)[0].Exception.Message}" TextWrapping="Wrap"/>

                </Border>

Yukarıdaki kesiti ValidationToolTipTemplate içerisinden aldım. Tooltip şablonu içerisinde buradaki Textblock'un Text'i görüldüğü üzere bir Binding ile beraber geliyor. Arkaplanda yolladığımız Exception'ların mesajlarının Tooltip içerisinde gözükmesini sağlayan sistem bu bindingden ibaret. Eğer burayı silersiniz mesajlarınız gözükmeyecektir o nedenle tasarımınızı değiştirirken bu noktaya dikkat etmekte fayda var.

Hepinize kolay gelsin.

Friday, July 03, 2009 5:16:38 PM (GTB Standard Time, UTC+02:00)  #    Comments [2]   Silverlight 3.0  | 
 Thursday, July 02, 2009

Silverlight içerisinde herhangi bir nesneye şeffaf fon vermek veya bir renk seçerken Alpha kanalını da ayarlamak mümkün fakat elinizde hali hazırda bir görsel varsa ve bu görsel içerisindeki belirli bir rengin şeffafa çevrilmesini istiyorsanız ne yapabilirsiniz?

Ne zaman lazım olacak ki?

"Chroma Key" denilen bu efektin en çok kullanıldığın yer fotoğraf veya videoların birleştirilmesi noktasında karşımıza çıkıyor. Örneğin koşan bir adam videosu var elinizde fakat bu adamı kendi fon görselinizde koşturmak istiyorsunuz. Bu durumda videonun fonunu silip yerine başka bir şeyler koyabiliyor olmanız gerekir. Aynı şey fotoğraflar için de geçerli. Tabi her konuda olduğu gibi bu konuda da belirli kurallar var. Bir şekilde bir resmin ve videonun fonunu silebilmek istiyorsanız aslında o videonun da uygun şekilde hazırlanmış olması gerekiyor.

Chroma Key'e uygun bir video.
Chroma Key'e uygun bir video.

Yukarıda görmüş olduğunuz kare bir videonun alınma. Fonun yeşil olması tabi ki şart değil. Bu notkada önemli olan şey video içerisinden almak istediğiniz obje ile fonun birbirine tezat renkler taşıması. Böylece bu videoyu gösterirken yeşil pikselleri bularak şeffaf hale çevirebileceğiz. Durum böyle olunca da rahatlıkla bu videonun arkasına başka bir video veya herhangi bir kontrol yerleştirebiliriz.

Peki nasıl yapacağız?

Bir video veya resim dosyasından bir rengi şeffaf hale getirmek için o dosyanın görselinde her pikseli tek tek gezmemiz gerekecek fakat özellikle video dosyalarından bahsedersek video içerisinde her kareyi de tek tek incelemek epey zahmetli olabilir. Oysa Silverlight 3.0 ile beraber gelen yeni özelliklerden biri olan PixelShader efektleri tam da bu iş için biçilmiş kaftan.

PixelShader efektleri zaten uygulandıkları görselin her pikseli gösterilmeden önce o pikseldeki renk değerlerine müdahale edebilen efektler şeklinde tasarlanıyor. Silverlight 3.0 ile Piksel Shader kullanımı makalemizde daha detaylı bilgi bulabilirsiniz.

Biz örneğimizde kullanmak üzere yeni bir PixelShader efekti yaratacağız. Bu efekt kendisine gelen her pikseli inceleyerek Chrome Key rengine yakın bir renk var ise o rengi şeffaf hale çevirecek. Tüm bu kontrol yapılırken tabi ki eldeki renk ile Chrome key renginin yakınlığı konusunda da bir parametre kullanmak durumundayız. Özetlemek gerekirse, eğer videomuzun fonu yeşil ile Chrome Key rengimiz de yeşil olacak ve PixelShader efektine yeşil rengini vereceğiz fakat duruma göre tam olarak RGB değerleri belli olan bir yeşil rengini değil de o yeşil rengine çok yakın diğer yeşilleri de şeffaflaştırmak isteyebiliriz. İşte bu yakınlık değerini Threshold denilen ayrı bir parametrede tutacağız.

[HLSL]

sampler2D input : register(S0);

 

float red : register(C0);

float green : register(C1);

float blue : register(C2);

float threshold : register(C3);

 

float4 main(float2 pos : TEXCOORD) : COLOR

{

    float4    color;

    float    rkey, gkey, bkey, thresh;

 

    thresh = threshold;               

    rkey = red/255.0;

    gkey = green/255.0;

    bkey = blue/255.0;

 

    color = tex2D(input, pos);

 

    if (abs(color.r - rkey) <= thresh)

    {

        if (abs(color.g - gkey) <= thresh)

        {

            if (abs(color.b - bkey) <= thresh)

            {

                // Şeffaflaştır

                color.a = 0.0;

            }

        }

    }

 

    return color;

}

Yukarıdaki kod efektimizim HLSL ile yazılmış hali. Konumuz HLSL olmadığı için detaylarına girmeyeceğim. Önemli olan bu şekilde HLSL efektini yazdıktan sonra efekti compile edip ortaya çıkan PS dosyasını Silverlight ile kullanmak. PixelShader efektlerinin Silverlight ile kullanımı konusunda Silverlight 3.0 ile Piksel Shader makalesini incelemeyi unutmayın.

[C#]

    public class AlphaShader : ShaderEffect

    {

        public AlphaShader()

        {

            this.PixelShader = new PixelShader();

            this.PixelShader.UriSource = new Uri("/Alpha.ps", UriKind.Relative );

 

            this.UpdateShaderValue(InputProperty);

            this.UpdateShaderValue(RedProperty);

            this.UpdateShaderValue(GreenProperty);

            this.UpdateShaderValue(BlueProperty);

            this.UpdateShaderValue(ThreshProperty);

        }

 

        public Brush Input

        {

            get { return (Brush)GetValue(InputProperty); }

            set { SetValue(InputProperty, value); }

        }

 

        public static readonly DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(AlphaShader), 0);

        public static readonly DependencyProperty RedProperty = DependencyProperty.Register("Threshold", typeof(double), typeof(AlphaShader), new PropertyMetadata(0.0, PixelShaderConstantCallback(0)));

        public static readonly DependencyProperty GreenProperty = DependencyProperty.Register("Red", typeof(double), typeof(AlphaShader), new PropertyMetadata(0.0, PixelShaderConstantCallback(1)));

        public static readonly DependencyProperty BlueProperty = DependencyProperty.Register("Green", typeof(double), typeof(AlphaShader), new PropertyMetadata(0.0, PixelShaderConstantCallback(2)));

        public static readonly DependencyProperty ThreshProperty = DependencyProperty.Register("Blue", typeof(double), typeof(AlphaShader), new PropertyMetadata(0.25, PixelShaderConstantCallback(3)));

 

        public double Threshold

        {

            get { return (double)GetValue(ThreshProperty); }

            set { SetValue(ThreshProperty, value); }

        }

 

        public double Red

        {

            get { return (double)GetValue(RedProperty); }

            set { SetValue(RedProperty, value); }

        }

 

        public double Green

        {

            get { return (double)GetValue(GreenProperty); }

            set { SetValue(GreenProperty, value); }

        }

 

        public double Blue

        {

            get { return (double)GetValue(BlueProperty); }

            set { SetValue(BlueProperty, value); }

        }

    }

Yukarıdaki sınıf bizim AlphaShader adını verdiğimiz kendi PixelShader efektimizin Silverlight içerisindeki tanımı. Söz konusu PixelShader efekti uygulama içerisindeki compile edilmiş Alpha.ps efektini kullanıyor. Gördüğünüz tüm Dependency Propoerty'ler de aslında HLSL'e gönderdiğimiz parametreler. Chroma Key rengimizin RGB değerlerini ayrı ayrı gönderirken Threshold değerini de 1 ile 0 arasında gönderiyoruz.

Artık efektimiz hazır olduğuna göre uygulamamızın arayüzünü de hazırlayabiliriz.

[XAML]

<UserControl x:Class="SilverlightApplication30.MainPage"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   Width="800" Height="600"

            xmlns:daron="clr-namespace:SilverlightApplication30">

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

        <Image Margin="8,18,86,69" Source="Desert.jpg"/>

        <MediaElement

           x:Name="myVideo"

           Margin="30,32,109,89"

           Source="ornek.wmv"/>

    </Grid>

</UserControl>

Gördüğünüz gibi örneğimizde basit bir şekilde bir resim ve üzerinde de bir video bulunuyor. Amacımız video içerisindeki yeşil kısmı kaldırıp sanki video içerisinde arkadaş resmin üzerinde hareket ediyormuş izlenimi yaratmak. Şimdi tekrar kod tarafına geçerek efektimizi MediaElement'imize uygulayalım.

[C#]

        void MainPage_Loaded(object sender, RoutedEventArgs e)

        {

            var x = new AlphaShader();

            x.Threshold = 0.37;

            x.Red = 91;

            x.Green =254;

x.Blue = 125;

            myVideo.Effect = x;

        }

Gördüğünüz gibi daha önceki adımlarda yarattığımız AlphaShader sınıfımızdan bir kopya alıp tüm Property'lerine uygun değerleri veriyoruz. Sonrasında da artık efektimizi MediaElement'in Effect'ine eşitliyoruz. Peki nasıl bir sonuç mu alıyoruz? Sonuç aşağıda.

PixelShader ile Chrome Key efekti.
PixelShader ile Chrome Key efekti.

Gördüğünüz gibi videomuz içerisindeki yeşil kısımlar tamamen yok oldu ve onun yerine çok daha farklı bir görsel yerleştirebildik. Videomuz oynarken de herhangi bir sorun olmayacak ve PixelShader efektimiz sürekli çalışarak bulduğu yeşil pikselleri şeffaf hale getirecek.

Hepinize kolay gelsin.

Thursday, July 02, 2009 11:03:09 AM (GTB Standard Time, UTC+02:00)  #    Comments [0]   Silverlight 3.0  | 
 Wednesday, July 01, 2009

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.

Wednesday, July 01, 2009 6:17:59 PM (GTB Standard Time, UTC+02:00)  #    Comments [1]   Silverlight 3.0  | 
Copyright © 2010 Daron Yöndem. Tüm hakları saklıdır.