Makale Özeti

Bu yazımızda Silverlight 3.0 ile beraber gelen DataForm kontrolünün kullanımını, veri bağlantısını ve özelleştirilmesini incelerek validasyon konusuna hızlı bir şekilde değineceğiz.

Makale

DataForm kontrolüne hızlı bir şekilde göz atıldığında aslında ASP.NET'teki DetailsView kontrolüne benzetilebilir. Bu önyargı ile hızlıca konumuza giriş yaparken gelin ilk olarak bir Silverlight 3 projesine nasıl DataForm kontrolünü ekleyebiliriz inceleyelim.

DataForm kontrolü sahnede...

DataForm kontrolü Silverlight ile beraber gelen harici kontrollerden biri. Yani DataForm kontrolü Silverlight 3'ün RunTime'ında bulunmuyor. Öyle hemen istediğimiz yerde anında kullanamıyoruz. Eğer bizim uygulamamız bu kontrolü kullanmak istiyorsa ona ait DLL'i referans alarak kendi XAP dosyası içerisinde taşımak zorunda. Tabi bu harici DLL'ler ile ilgili cachleme vs işlemleri de mümkün fakat bu konuda makalemizin şimdilik dışında.

Durum böyle ise DataForm kontrolünü kullanabilmek için hemen  Visual Studio içerisinde yeni bir SL 3.0 projesi yaratıp projemize sağ tıklayarak "Add Reference" diyip System.Windows.Controls.Data.DataForm'ı referans olarak eklemeliyiz. Böylece artık bu DLL içerisindeki kontrolleri kullanabiliriz. Fakat daha işimiz bitmedi. Projemize eklemiş olduğumuz bu Assembly içerisindeki kontrolleri XAML tarafında veya Blend 3 içerisinde kullanabilmemiz için ayrıca XAML tarafına da DLL'imizi tanıtmamız gerekiyor.

[XAML]

<UserControl x:Class="SilverlightApplication10.MainPage"

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

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

   Width="400" Height="300"

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

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

        <dataControls:DataForm x:Name="birDataForm"></dataControls:DataForm>

    </Grid>

</UserControl>

Yukarıda gördüğünüz şekli ile DLL'imizi dataControls adı altında XAML tarafına da aldık. Sonrasında da içerisinde bulunduğumuz sayfadaki Grid'in içine yine dataControls XML namespace'i üzerinden giderek Assembly içerisinde DataForm sınıfından bir instance alıyoruz. Artık sahnede bir DataForm var. Tüm bu işlemleri otomatik olarak yapmak isterseniz Visual Studio içerisinde XAML dosyasını açarak araç çubuğundan da DataForm kontrolünü sürükleyip sahneye bırakabilirsiniz. Visual Studio sizin için otomatik olarak DLL'i referans alıp gerekli XAML tanımlamalarını da yapacaktır. Bu noktada ufak bir detaya dikkat çekmek istiyorum. Şu an Silverlight 3.0 Beta olduğu için Visual Studio içerisinde designer tarafında desteği biraz zayıf. O nedenle araç çubuğundan herhangi bir kontrolü XAML dosyanıza sürükleyip bırakmak isterseniz sadece kod tarafına bırakabileceğinizi söylemem gerek.

Hemen bir veri bağlayalım!

Kontrolümüz artık sahnede olduğuna göre hemen bir veri bağlayarak neler yapabiliyoruz göz atalım. İlk olarak bağlayacağımız veriyi temsil edecek olan sınıfımızı yaratalım.

[VB]

Public Class Entities

    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 Double

        Public Property Satis() As Double

            Get

                Return PSatis

            End Get

            Set(ByVal value As Double)

                PSatis = value

            End Set

        End Property

 

    End Class

End Class

[C#]

    public class Entities

    {

        public class Urun

        {

            private string PAdi;

            public string Adi

            {

                get { return PAdi; }

                set { PAdi = value; }

            }

 

            private double PSatis;

            public double Satis

            {

                get { return PSatis; }

                set { PSatis = value; }

            }

        }

    }

Gördüğünüz gibi sınıfımızın adı Urun ve içerisinde de iki adet farklı Property var. Bu sınıfımızdan yola çıkarak birden çok Urun yaratıp bunları da DataForm kontrolümüze veri kaynağı olarak vereceğiz. Ama gelin bunun öncesinde tek bir Urun sınıfı yaratarak DataForm'a verelim bakalım neler yapacak.

[VB]

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

        birDataForm.CurrentItem = New Entities.Urun() With {.Adi = "Ürün Adi", .Satis = 20}

    End Sub

[C#]

        void  MainPage_Loaded(object sender, RoutedEventArgs e)

        {

            birDataForm.CurrentItem = new Entities.Urun { Adi = "Ürün Adi", Satis = 20 };

        }

Daha önceden XAML tarafında yaratmış olduğumuz DataForm kontrolüne isim olarak birDataForm ismini verdiğimiz için kod tarafında da aynı isimle ulaşıp şimdilik DataForm'un CurrentItem özelliğine yeni bir nesne atıyoruz. Söz konusu nesne daha önce tanımlamış olduğumuz Urun sınıfının bir instance'ı.

DataForm içerisinde tek bir kaydın düzenlenmesi.
DataForm içerisinde tek bir kaydın düzenlenmesi

Gördüğünüz üzere DataForm otomatik olarak kendisine bağlanan veri içerisinde tüm Property'ler için hem Textblock ve Textbox'lar yerleştirebiliyor hem de söz konusu Property'lerin adlarını da yanına yazarak aslında kabaca bir veri giriş ve düzenleme ekranı oluşturuyor. DataForm içerisinde sol üstte bulunan Edit düğmesine tıklarsanız ortaya veriyi düzenleyebileceğiniz bir ekran gelirken "Save" düğmesi de hemen altta kendini gösteriyor. Tabi ki bu aşamadan sonra özelleştirilmesi gereken birçok nokta var. İşte biz de makalemizin devamında bu noktalara değineceğiz.

MetaData aşkı!

Eğer ASP.NET Dynamic Data projeleri üzerine biraz çalışma şansınız olduysa veri kaynağı olarak kullanılan sınıflara verilen MetaData'lar ile beraber birçok şeyin ayarlanabildiğini hatırlayacaksınız. DataForm ile beraber çalışırken de aslında çoğu kuralı MetaData'lar ile DataForm'a bağlayacağımız veri kaynağı seviyesinde ayarlamamız gerekiyor. Örneğin yukarıdaki projemizde Urun adındaki nesnemizi tanımlarken Adi ve Satis Property'lerinde tabi ki Türkçe karakterler kullanmadık. Oysa DataForm bu Property'leri istemci tarafına açarken belki de Türkçe karakterler de içeren düzgün isimleri açmalı değil mi?

[VB]

Public Class Entities

    Public Class Urun

 

        Private PAdi As String

        <System.ComponentModel.DataAnnotations.Display(Name:="Adı")> _

        Public Property Adi() As String

            Get

                Return PAdi

            End Get

            Set(ByVal value As String)

                PAdi = value

            End Set

        End Property

 

        Private PSatis As Double

        <System.ComponentModel.DataAnnotations.Display(Name:="Satış")> _

        Public Property Satis() As Double

            Get

                Return PSatis

            End Get

            Set(ByVal value As Double)

                PSatis = value

            End Set

        End Property

 

    End Class

End Class

[C#]

    public class Entities

    {

        public class Urun

        {

 

            private string PAdi;

            [System.ComponentModel.DataAnnotations.Display(Name = "Adı")]

            public string Adi

            {

                get { return PAdi; }

                set { PAdi = value; }

            }

 

            private double PSatis;

            [System.ComponentModel.DataAnnotations.Display(Name = "Satış")]

            public double Satis

            {

                get { return PSatis; }

                set { PSatis = value; }

            }

 

        }

    }

Yukarıdaki kod içerisinde Urun sınıfımızı tanımlarken neleri değiştirediğimize dikkat edelim. Her bir Property'i tanımlarken bir de MetaData veriyoruz. System.ComponentModel.DataAnnotations sınıfı altında kullanabileceğiniz bir çok farklı MetaData'yı bulabilirsiniz. Bunların bazılarına makalemiz içerisinde göz atacağız. Şu an için Display MetaData'sını vererek söz konusu Property'lerin DataForm tarafından hangi isimle gösterilmesi gerektiğini belirtiyoruz. Tabi ki bu noktada istediğimiz gibi Türkçe karakterler kullanabiliriz. Bundan sonraki örnek kodlarda Urun sınıfının tüm tanımını değil sadece MetaData koyduğumuz satırların etrafını yazacağım.

[VB]

        <System.ComponentModel.DataAnnotations.Display(Name:="Satış", Description:="Bu satış değeridir")> _

        Public Property Satis() As Double

Yukarıdaki şekli ile tanımlanan bir Display MetaData'sında ek olarak bir de Description verisi bulunuyor. Bu parametreye herhangi bir değer verilmesi halinde DataForm içerisinde bu Property'nin yanında bir ünlem işareti belirecektir. Kullanıcılar söz konusu ünlem işaretinin üzerine fareleri ile geldiklerinde ise açıklamanızı görebilirler.

MetaData içerisinde Description yer alırsa...
MetaData içerisinde Description yer alırsa...

Şu ana kadar yaptığımız işlemlerin hepsinde belki de en sinir bozucu noktalardan biri DataForm içerisinde tüm Property'lerin sınıf tanımındaki sıra ile gösteriliyor olmasıdır. Aslında bu sırayı da değiştirebiliyoruz.

[VB]

        Private PAdi As String

        <System.ComponentModel.DataAnnotations.Display(Order:=1)> _

        Public Property Adi() As String

            Get

                Return PAdi

            End Get

            Set(ByVal value As String)

                PAdi = value

            End Set

        End Property

 

        Private PSatis As Double

        <System.ComponentModel.DataAnnotations.Display(Name:="Satış", Description:="Bu satış değeridir", Order:=0)> _

        Public Property Satis() As Double

            Get

                Return PSatis

            End Get

            Set(ByVal value As Double)

                PSatis = value

            End Set

        End Property

Display MetaData'sını tanımlarken verebileceğiniz Order parametresi doğrudan bu Property'lerin hangi sıra ile DataForm içerisinde gösterileceğini belirliyor. Sıfırdan başlayarak vereceğiniz bu sayılarla küçükten büyüğe doğru gidecek sırada Property'ler ekrana getirilecektir. Bizim örneğimizde üstte Satis altta Adi parametreleri yer alıyor.

Binding yollarında...

İlk örneğimizde DataForm'a bağladığımız nesne kod tarafında içerisinde bulunduğu scope dışında yaşayamayacağı için pek anlamlı bir örnek olmamıştı. DataForm içerisinde edit işlemi yapılsa da söz konusu bağlı değişken arkada yaşamadığı için edit işleminin de anlamı kalmıyor. Fakat eğer DataForm'a bağladığınız değişkenleri kod tarafında sürekli canlı tutarsanız DataForm içerisindeki değişikliklerin doğrudan nesneye yansıtıldığını da görebilirsiniz. Duruma göre bu işlevselliği değiştirmek veya bazen arka taraftaki nesnede bulunan bazı Property'leri DataForm içerisinde göstermemek de isteyebilirsiniz. Örneğin bizim Urun nesnesinin bir PK property'si olsaydı kesin onu göstermek istemezdir.

[VB]

        <System.ComponentModel.Bindable(False)> _

        Public Property Adi() As String

Yukarıdaki gibi herhangi bir Property'yi doğrudan Bindable False olarak işaretleyebilirsiniz. Böylece söz konusu Property hiçbir şekilde bağlı olduğu kontroller tarafından gösterilmeyecektir. Diğer yandan bu Property'nin gösterilmesi fakat değerinin değiştirilemesini isterseniz bu sefer de aşağıdak şekilde Bindable'a ikinci bir parametre vererek tek yönlü veri bağlantısı oluşturabilirsiniz.

[VB]

        <System.ComponentModel.Bindable(True, ComponentModel.BindingDirection.OneWay)> _

        Public Property Adi() As String

Yukarıdaki şekli ile bu Property DataForm'un edit modunda gözükse de değeri değiştirilemeyecektir.

Ya Validation gerekirse?

Belki de DataForm kontrolünün en can alıcı noktalarından biri tüm validasyon işlemlerini de kısmen MetaData üzerinden yapabiliyor olmamız. Örneğin bazı Property'lerin kullanıcı tarafından boş geçilememesini isteyebilirsiniz. Bu ve bu gibi tüm Validation işlemleri için yine System.ComponentModel.DataAnnotations sınıfı altındaki tanımlardan faydalanabiliriz.

[VB]

        <System.ComponentModel.DataAnnotations.Required(ErrorMessage:="Boş geçilemez")> _

        Public Property Adi() As String

Yukarıdaki örnek kodda da görebileceğiniz üzere Required olarak işaretlediğimiz Adi Property'sine bir de ErrorMessage vermişiz. DataForm kontrolü bu Property ile ilgili gerekli validasyonları yapmakla kalmayacak, herhangi bir sorun olduğunda MetaData içerisinde tanımladığımız hatayı da güzel bir şekilde kullanıcıya gösterecek.

Basit bir validasyon örneği!
Basit bir validasyon örneği!

Validasyon yöntemlerinden bazıları bir önceki örneğimizdeki gibi hazır bir şekilde tanımlanmış bizim kullanımızı bekliyor. Bunlardan biri de doğrudan sayısal değerlerin alabilecekleri değer aralığını kontrol eden Range sınıfı.

[VB]

        <System.ComponentModel.DataAnnotations.Range(1, 10, ErrorMessage:="Aman!")> _

        Public Property Satis() As Double

Range MetaData'sını biz örneğimizde anlamlı olması açısından Satis Property'sine verelim. Artık yukarıdaki tanımlama ile beraber Satis Property'si kesinlikle 1 ile 10 arasında olmak zorunda. Aksi durumda MetaData içerisinde tanımladığımız ErrorMessage kullanıcıya gösterilecektir.

[VB]

        <System.ComponentModel.DataAnnotations.StringLength(10)> _

        Public Property Adi() As String

Hazır gelen kontrollerden biri de StringLenght kontrolü. Bu MetaData ile beraber söz konusu Property'e atanabilecek metin uzunluğunun en yüksek değerini tanımlamış oluyoruz. Böylece kullanıcılar daha yüksek değerler girdiğinde eğer tanımlanmış ise özel hata mesajları da gösterilebiliyor.

Eğer isterseniz tüm bu validasyonların yanı sıra daha karmaşık RegularExpression yapıları da kullanabilirsiniz. Bizim örneğimizde varsayalım ki kullanıcıların ürünlere isim verirken hep büyük harf ile başlamalarını istiyoruz. Bu durumda aşağıdaki gibi bir RegEx tanımlamasını işimizi görecektir.

[VB]

        <System.ComponentModel.DataAnnotations.RegularExpression("^[A-Z]+[a-zA-Z]*$", ErrorMessage:="Büyük harfle başlamalı")> _

        Public Property Adi() As String

Hardcore Validasyon?

Bazı durumlarda validasyon ile ilgili RegEx'ler de işinizi görmeyebilir. Bizim örneğimizde bu duruma uygun anlamlı bir senaryo yaratmak zor olsa da diyelim ki ürünlerimiz A harfi ile başlıyorsa fiyatlarının kesinlikle 10 ile 20 arasında olması gerekiyor. Bu senaryoyu gerçek hayata taşırken aslında farklı Property'lerin farklı iş kuralları ile kontrol edilmesi gerektiğini de düşünebilirsiniz. Böyle bir durumda tamamen farklı bir mekanizma kullanabilmek için CustomValidation yapısı bizi bekliyor.

[VB]

    Public Class Kontrol

        Public Shared Function UrunKontrol(ByVal BirUrun As Urun) As Boolean

            If BirUrun.Adi.StartsWith("A") Then

                If BirUrun.Satis > 10 And BirUrun.Satis < 20 Then

                    Return True

                Else

                    Return False

                End If

            Else

                Return True

            End If

        End Function

    End Class

[C#]

    public class Kontrol

    {

        public static bool UrunKontrol(Urun BirUrun)

        {

            if (BirUrun.Adi.StartsWith("A"))

            {

                if (BirUrun.Satis > 10 & BirUrun.Satis < 20)

                {

                    return true;

                }

                else

                {

                    return false;

                }

            }

            else

            {

                return true;

            }

        }

    }

Yukarıdaki gördüğünüz kod içerisinde Kontrol adında bir sınıfın içinde Shared / Static olarak tanımlanmış bir Validasyon metodu bulunuyor. Metod aslında alıştığımız .NET metodlarından farklı değil. UrunKontrol adını verdiğimiz bu metod kendisine parametre olarak verilen bir Urun nesnesini kontrol ederek geriye True veya False şeklinde Valid / Uygundur veya InValid / Uygun Değildir mesajı döndürmüş oluyor. Bu hazırladığımız validasyon metodunun herhangi bir Urun nesnesine uygulanması için ise Urun nesnesinin tanımına ufak bir MetaData eklemesi yeterli olacaktır.

[VB]

    <System.ComponentModel.DataAnnotations.CustomValidation(GetType(Kontrol), "UrunKontrol", ErrorMessage:="Olmadı!")> _

    Public Class Urun

[C#]

    [System.ComponentModel.DataAnnotations.CustomValidation(typeof(Kontrol), "UrunKontrol", ErrorMessage = "Olmadı!")]

    public class Urun

    {

    }

CustomValidation olarak tanımladığımız bu kontrol mekanizmasını sınıfımıza bağlarken ilk olarak validasyon yapacak olan sınıfın tipini veriyoruz. Sonrasında bu sınıf içerisinde hangi metodun kullanılacağını bir String parametre olarak verip bir de eğer istiyorsak validasyon işlemi False döndürdüğünde gösterilmek üzere ErrorMessage ayarlıyoruz. İsterseniz bu mekanizmayı sınıf bazında değil doğrudan Property bazında da kurabilirsiniz.

Herşey kontrol altında...

Tüm bahsettiğimiz validasyon sistemlerine ek olarak bazen bir ürün düzenlenmesi ile ilgili istemci tarafında DataForm ile yaratılan süreçlere müdahale etmek de isteyebilirsiniz. Örneğin bir ürün kaydedilirken adı boş ise belki ona varsayılan bir isim vermek isteyeceksiniz veya bir ürünün kayıt moduna geçildikten sonra herhangi bir değişiklik yapılmadan kayıt modundan çıkılmasını engellemek de isteyebilirsiniz. Bu gibi daha birçok senaryo olabilir.

[VB]

    Public Class Urun

        Implements ComponentModel.IEditableObject

 

        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 Double

        Public Property Satis() As Double

            Get

                Return PSatis

            End Get

            Set(ByVal value As Double)

                PSatis = value

            End Set

        End Property

 

        Public Sub BeginEdit() Implements System.ComponentModel.IEditableObject.BeginEdit

 

        End Sub

 

        Public Sub CancelEdit() Implements System.ComponentModel.IEditableObject.CancelEdit

 

        End Sub

 

        Public Sub EndEdit() Implements System.ComponentModel.IEditableObject.EndEdit

 

        End Sub

    End Class

[C#]

        public class Urun : IEditableObject

        {

            private string PAdi;

            public string Adi

            {

                get { return PAdi; }

                set { PAdi = value; }

            }

 

            private double PSatis;

            public double Satis

            {

                get { return PSatis; }

                set { PSatis = value; }

            }

 

            public void BeginEdit()

            {

                throw new NotImplementedException();

            }

 

            public void CancelEdit()

            {

                throw new NotImplementedException();

            }

 

            public void EndEdit()

            {

                throw new NotImplementedException();

            }

        }

Kendi sınıfınıza IEditableObject interface'ini implemente ettiğiniz anda artık sınıfınızın BeginEdit, CancelEdit ve EndEdit gibi durumları olacak. Bu durumlara dair kod bloklarına yazacağınız kodlar edit işlemi başladığında, iptal edildiğinde veya bittiğinde çalıştırılacaktır. Böylece siz de bu süreçlerde nesne ile ilgili değişiklikleri rahatlıkla yapabilirsiniz.

Çoklu kayıt desteği de var.

DataForm kontrolünü epey karıştırmış olsak da aslında hiç bakmadığımız bir özelliği var. Örneklerimizin başından beridir sadece tek bir nesne yarattık ve DataForm'un CurrentItem'ına atadık. Oysa DataForm kontrolünün ItemsSource'una da birden çok nesne içeren listeler bağlanabilir.

 [VB]

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

        Dim liste As New System.Collections.ObjectModel.ObservableCollection(Of Entities.Urun)

        liste.Add(New Entities.Urun() With {.Adi = "Ürün Adi", .Satis = 20})

        liste.Add(New Entities.Urun() With {.Adi = "Ürün Adi2", .Satis = 30})

        liste.Add(New Entities.Urun() With {.Adi = "Ürün Adi3", .Satis = 40})

        birDataForm.ItemsSource = liste

    End Sub

[C#]

        void MainPage_Loaded(object sender, RoutedEventArgs e)

        {

            System.Collections.ObjectModel.ObservableCollection<Entities.Urun> liste = new System.Collections.ObjectModel.ObservableCollection<Entities.Urun>();

            liste.Add(new Entities.Urun { Adi = "Ürün Adi", Satis = 20 });

            liste.Add(new Entities.Urun { Adi = "Ürün Adi2", Satis = 30 });

            liste.Add(new Entities.Urun { Adi = "Ürün Adi3", Satis = 40 });

            birDataForm.ItemsSource = liste;

        }

Kodumuzda bu sefer tamamen deneme amaçlı olarak içerisinde birden çok Urun bulunan bir ObservableCollection kullanıyoruz. Uygulamamızı çalıştırdığımıda DataForm kontrlünün sağ üstünde navigasyon kontrolleri de yerini alıyor. Böylece artık DataForm kontrolü içerisinde birden çok nesnenin de gezilerek düzenlenebileceğini görmüş olduk.

Çoklu kayıt düzenleme ekranı.
Çoklu kayıt düzenleme ekranı.

Yukarıdaki ekran görüntüsünde sağ üst köşede gördüğünüz düğmeler sadece kayıtlar arasında gezintiyi sağlamıyor. Ayrıca bulunan kaydın düzenlenebilmesinin yanı sıra yeni bir kayıt eklenebilmesini hatta silinebilmesini de sağlayabiliyorlar. Hali hazırda nesnemize bir ObservableCollection bağladığımız için zaten tüm değişiklikler otomatik olarak nesneye de yansıyacaktır.

AutoGenerateFields ?

Sanırım ASP.NET ile biraz uğraşan herkes AutoGenerateFields deyince ne demek istediğimi anlayacaktır. Bir DataForm'un normal şartlarda kendisine verdiğimiz veriye uygun şekilde gerekli TextBox vs kayıt düzenleme kontrollerini otomatik olarak yaratmasını sağlayan özellik AutoGenerateFields'in varsayılan değeri olan "True" değerinde saklı. Eğer AutoGenerateFields özelliğini False olarak ayarlarsanız artık veri kaynağından gelen her verinin ne şekilde görsel ekrana yansıtılacağını tek tek sizin ayarlamanız gerekecektir. Tabi bu durum da bazı senaryolarda özelleştirme adına şart oluyor. Şimdi gelin bu konunun detaylarına bakalım.

[XAML]

        <dataControls:DataForm AutoGenerateFields="False" x:Name="birDataForm">

            <dataControls:DataForm.Fields>

                <dataControls:DataFormCheckBoxField />

                <dataControls:DataFormComboBoxField />

                <dataControls:DataFormDateField />

                <dataControls:DataFormTemplateField />

                <dataControls:DataFormTextField />

            </dataControls:DataForm.Fields>

        </dataControls:DataForm>

Yukarıdaki kod çalışır bir kod olmayacaktır. Fakat kabaca bir DataForm'un içerisinde gösterilecek verilerin ayarlanması ile ilgili kullanabileceğimiz Field tiplerini ve DataForm içerisine nasıl yerleştirebileceğimizi inceleyebilirsiniz. Bu Field tiplerinin her biri aslında farklı veri tiplerini hedefliyorlar. Örneğin CheckBoxField Boolean tipindeki verilerin gösterimi için rahatlıkla kullanılabilirken TextField ise metin tabanlı ve özünde TextBox olarak gösterilecek verileri temsil edecektir. Eğer bu Field tipleri size yeterli gelmiyorsa ve kendi özel Field tasarımınızı yaratmak istiyorsanız bu sefer de DataFormTemplateField'i kullanabilirsiniz.

[XAML]

        <dataControls:DataForm

           AutoGenerateFields="False"

           x:Name="birDataForm">

            <dataControls:DataForm.Fields>

                <dataControls:DataFormTextField

                   FieldLabelContent="Kayıt Adı"

                   Binding="{Binding Adi}" />

                <dataControls:DataFormTextField

                   FieldLabelContent="Satış Sayısı"

                   Binding="{Binding Satis}" />

            </dataControls:DataForm.Fields>

        </dataControls:DataForm>

Bir önceki adımda veri bağlantısını da yaptığımız DataForm üzerinden ilerlersek ilk olarak AutoGenerateFields özelliğini False olarak ayarlayıp sonrasında da iki tane TextField ekliyoruz. Her bir TextField'in veri kaynağından hangi veriyi alıp göstereceğini belirlemek için tabi ki veri kaynağımız olan nesnelerin property'lerine ait adları vermemiz gerekiyor. Bu aşamada her bir Field'in Binding özelliğine bir Binding atıyoruz ve Property adı ile veri bağlantısını da tamamlıyoruz. Son olarak yine her bir TextField'e de FieldLabelContent vererek bu Field'ler için yaratılacak TextBox'ların yanına konacak Label'ların da içeriğini belirlemiş oluyoruz. Ayrıca isterseniz FieldLabelPosition gibi Field'lere ayrı farklı özellikleri de değiştirerek ana görsel öğelerin dizilimine müdahale edebilirsiniz.

Eğer DataForm kontrolüne bağladığınız nesnelerin çok sayıda Property'si varsa bunları belirli gruplar ve altbaşlıklar ile de göstermek isteyebilirsiniz. Bunun için DataFormFieldGroup nesnesini kullanabilir hatta bu grupların arasına da DataFormSeparator'lar koyabilirsiniz.

[XAML]

        <dataControls:DataForm

           AutoGenerateFields="False"

           x:Name="birDataForm">

            <dataControls:DataForm.Fields>

                <dataControls:DataFormHeader

                   Content="Düzenlenecek şeyler" />

                <dataControls:DataFormSeparator />

                <dataControls:DataFormFieldGroup

                   Orientation="Horizontal">

                    <dataControls:DataFormTextField

                       FieldLabelPosition="Top"

                       FieldLabelContent="Kayıt Adı"

                       Binding="{Binding Adi}" />

                    <dataControls:DataFormTextField

                       FieldLabelPosition="Top"

                       FieldLabelContent="Satış Sayısı"

                       Binding="{Binding Satis}" />

                </dataControls:DataFormFieldGroup>

            </dataControls:DataForm.Fields>

        </dataControls:DataForm>

Yukarıdaki kod içerisinde ilk olarak bir FormHeader bulunuyor. Sonrasında bir Separator da kullandıktan sonra elimizdeki TextField'leri bir Fieldgroup içerisine aldık. FieldGroup'un Orientation özelliğini de Horizontal yaptığımızda artık bu grup içerisindeki kayıt düzenleme nesneleri yan yana gösterilecektir.

Özelleştirilmiş bir DataForm kontrolü.
Özelleştirilmiş bir DataForm kontrolü.

Daha da özelleştirelim, daha da!

Eğer yukarıdaki Field yapılarını özelleştirmek sizin ihtiyaçlarınızı gidermediyse aslında bir adım daha ileri giderek tüm görsel yapıyı değiştirme şansınız da var. Bunun için artık DataForm'un DisplayTemplate ve EditTemplate özelliklerine eğilmemiz şart.

[XAML]

        <dataControls:DataForm

           AutoGenerateFields="False"

           x:Name="birDataForm">

            <dataControls:DataForm.HeaderTemplate>

                <DataTemplate></DataTemplate>

            </dataControls:DataForm.HeaderTemplate>

            <dataControls:DataForm.DisplayTemplate>

                <DataTemplate></DataTemplate>

            </dataControls:DataForm.DisplayTemplate>

            <dataControls:DataForm.EditTemplate>

                <DataTemplate></DataTemplate>

            </dataControls:DataForm.EditTemplate>

            <dataControls:DataForm.InsertTemplate>

                <DataTemplate></DataTemplate>

            </dataControls:DataForm.InsertTemplate>

        </dataControls:DataForm>

Yukarıda gördüğünüz şekilde düzenlenen Template / Şablon yapıları birer DataTemplate olarak tanımlanır ve bu şablonlar içerisinde tanımlı görsel tasarımlar doğrudan DataForm kontrolü tarafından kullanılır.

[XAML]

        <dataControls:DataForm

           AutoGenerateFields="False"

           x:Name="birDataForm">

            <dataControls:DataForm.DisplayTemplate>

                <DataTemplate>

                    <StackPanel>

                        <TextBlock

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

                        <TextBlock

                           Text="{Binding Satis}"></TextBlock>

                    </StackPanel>

                </DataTemplate>

            </dataControls:DataForm.DisplayTemplate>

            <dataControls:DataForm.EditTemplate>

                <DataTemplate>

                    <StackPanel>

                        <TextBox

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

                        <TextBox

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

                    </StackPanel>

                </DataTemplate>

            </dataControls:DataForm.EditTemplate>

        </dataControls:DataForm>

Yukarıdaki XAMl içerisinde DataForm kontrolümüzün DisplayTemplate ve EditTemplate şablonlarına basit birer StackPanel yerleştiriyoruz. Bu StackPanel'ler içerisinde DisplayTemplate'te TextBlock'lar var, EditTemplate'te ise TextBox'lar var. Tüm bu kontrollerin Text özellikleri veri kaynağından uygun Property'lere bağlı durumda. Veri bağlama işlemini yine klasik Binding sistemi ile yapıyoruz. Kontrol normalde TextBlock'ları gösterirken düzenleme moduna geçince ise EditTemplate içerisindeki TextBox'ları gösterecektir. Tabi siz örneklerinizde basit birer StackPanel yerine çok daha özelleştirilmiş görsel tasarımlar kullanabilirsiniz.

Sonuç

Görüldüğü üzere DataForm kontrolü kendisinden beklenenden çok daha fazlasını sunabilecek bir kontrol olarak karşımızda. İş uygulamalarında sürekli hazırladığınız çoğu formun Silverlight içerisinde rahatlıkla ve en önemlisi de hızlı bir şekilde oluşturulabilmesini sağlıyor. İster basit ister karışık validasyon kurallarınız olsun, ister basit ister karışık ve özelleştirilmiş bir tasarımınız olsun DataForm kontrolü her durumda size uyum sağlayabilecek şekilde tasarlanmış. Eh hadi ;) Sıra sizde...

Hepinize kolay gelsin....