Makale Özeti

Silverlight Toolkit ile beraber gelen Label kontrolünün özelleştirilmesini ve databind işlemlerinin nasıl yapılabileceğini görsel şablonlarla beraber inceliyoruz.

Makale

Silverlight ilk çıktığı günlerde en çok şaşırdığımız noktalar biri "Label" adında bir kontrolün bulunmamasıydı. İşlevsellik olarak aynı çözümü sunan TextBlock kontrolünü çok kısa bir sürede keşfetmiş olsak da neden isminin değiştiğini pek anlayalamıştık. Bugünlerde Silverlight Toolkit paketi ile beraber özel bir Label kontrolü geldi.

Nedir TextBlock ile Label'ın farkı?

Aslında kaba tanımı ile TextBlock kontrolü Label'ın yapı taşıdır. Bir Label kontrolü ControlTemplating desteklerken TextBlock desteklemez. Zaten Label Template'leri oluştururken biz de TextBlock'lardan faydalanacağız. Özetle Label'lar gelişmiş TextBlock kontrolleridir de diyebiliriz. Sözü daha çok uzatmadan gelin neler yapabildiğimize göz atalım.

Not: Silverlight Toolkit'i kullanabilmeniz için CodePlex üzerindeki adresten kütüphaneyi indirerek içerisindeki Microsoft.Windows.Controls.dll dosyasını projenize referans olarak eklemelisiniz.

Bir Label kontrolünü Silverlight Toolkit'in referans alınmış olduğu herhangi bir projede rahatlıkla kullanabilirsiniz. Expression Blend içerisinde "Asset Library" kısmında "Custom Controls" sekmesinde Label kontrolünü bulabilirsiniz. TextBlock'larda da oluğu gibi herhangi bir Label içerisine yazı yazmak için Content özelliğinden faydalanabilirsiniz.

[XAML]

<UserControl x:Class="SilverlightApplication2.Page"

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

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

  Width="400" Height="300" xmlns:controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls">

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

      <controls:Label HorizontalAlignment="Left" VerticalAlignment="Top" Content="Deneme Amaçlı Metin"/>

    </Grid>

</UserControl>

Basit bir şekilde Label kontrolünün kullanımına dair yukarıdaki XAML kodunu inceleyebilirsiniz. Bir TextBlock ile Label kontrolünü birbirinden ayıran özelliklerden ilki Label kontrolünün BorderBrush alabiliyor olması. Hatta sadece bu kadarla kalmayıp bir Label'ın hangi kenarlarında Border bulunacağına da karar verebiliyorsunuz.

Label kontrolünün BorderBrush ayarları.
Label kontrolünün BorderBrush ayarları.

Aynı şekilde isterseniz bir Label için Background da belirleyebilirsiniz. Fakat makalemizin başından beridir bahsettiğimiz Label'ın en önemli özelliği aslında ControlTemplating'e olanak tanıması. Gelin şimdi Expression Blend içerisinde Label kontrolümüze sağ tıklayarak gelen menüden "Edit Control Parts / Create Empty" komutunu verelim. Böylece hali hazırda sahnede olan Label'ın görselliği yok varsayılarak bizim Label kontrolünün yapısını tekrar tasarlayabilmemiz sağlanacak. Bunun için ilk aşamada karşınıza gelen pencerede bu şablona bir de isim vermeniz gerek. Unutmayın hazırlanan şablonlar sonrasında birden çok Label'a linklenerek merkezi bir yerden kullanılabilir.

Label kontrolü için yeni bir ControlTemplate yaratıyoruz.
Label kontrolü için yeni bir ControlTemplate yaratıyoruz.

ControlTemplate'imizi yarattıktan sonra Blend bizi otomatik olarak Template tasarımına götürecektir. Bu sahnede otomatik olarak gelen Grid nesnesini bir Canvas'a çevireceğiz. Bu seçimi tamamen örneğin kolay ilerlemesi için yapıyoruz. Siz kendi tasarımlarınızda farklı Layout kontrolleri tabi ki kullanabilirsiniz.

ControlTemplate tasarımımız bitmek üzere.
ControlTemplate tasarımımız bitmek üzere.

Tasarımımızda Canvas'ın içerisinde bir Rectangle koyarak Fill özelliğine de Radial bir GradientBrush atadık. Rectangle'ın önünde de bir TextBlock koyuyoruz. Label içerisinde metni gösterecek olan bu TextBlock kontrolü olacak. Label kontrolünün Content özelliğine verilen değerlerin otomatik olarak şablon içerisinde bu TextBlock'un Content'ine aktarılmasını sağlamalıyız. Bunu da ancak TemplateBinding ile yapabiliriz.

Blend arayüzünden TemplateBinding ayarlarımızı yapıyoruz.
Blend arayüzünden TemplateBinding ayarlarımızı yapıyoruz.

Blend'in arayüzünde şablonumuzu tasarlarken TextBlock kontrolümüzü seçtikten sonra ekranın sağında kalan "Properties" sekmesinden söz konusu TextBlock'un Content özelliğini ayarladığımız yerin hemen yanındaki ufak kareye tıklıyoruz. Gelen menüden "Template Binding" komutunu verdikten sonra Blend bize ana kontrolün hangi özelliğinin şablondaki bahsi geçen özelliğe bağlanacağını soruyor. Tabi biz de hemen Content özelliğini seçiyoruz. Böylece Label kontrolünün Content özelliğini şablonun içindeki TextBlock'un Content özelliğine bağlamış olduk.

Template tasarımı modundan çıkalım.
Template tasarımı modundan çıkalım.

Artık tasarımımızı tamamladığımızda göre şablon tasarım modundan çıkıp ana uygulamaya geri dönebiliriz. Artık Label kontrolünün Content'ini değiştirdiğinizde ayarladığınız görsellik içindeki Textblock'a yerleştiğini görebilirsiniz. En güzel de yeni bir Label eklediğinizde aynı şablonu kullanmasını sağlayabilirsiniz.

Hazırladığımız şablonu istediğimiz Label kontrolünde kullanabiliriz.
Hazırladığımız şablonu istediğimiz Label kontrolünde kullanabiliriz.

Uygulamanıza yeni bir Label ekledikten sonra hazırladığınız şablonu bu Label üzerinde de kullanmak istiyorsanız doğrudan söz konusu Label'a sağ tuş ile tıklayarak gelen menünden "Edit Control Parts / Apply Resource" diyerek şablonunuzu adı ile seçebilirsiniz. Böylece geri dönüp bu şablonda bir değişiklik yaptığınızda birden çok Label'da değişiklik yapmış olacaksınız. Merkezi yönetim :)

Yaptığımız tüm işlemlerin sonucunda aşağıdaki XAML kodu yaratılıyor.

[XAML]

<UserControl x:Class="SilverlightApplication2.Page"

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

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

  Width="400" Height="300" xmlns:controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls">

  <UserControl.Resources>

    <ControlTemplate x:Key="DenemeSablon" TargetType="controls:Label">

      <Canvas>

        <Rectangle Height="50" Width="200" Stroke="#FF000000">

          <Rectangle.Fill>

            <RadialGradientBrush>

              <GradientStop Color="#FF000000"/>

              <GradientStop Color="#FFFFFFFF" Offset="1"/>

            </RadialGradientBrush>

          </Rectangle.Fill>

        </Rectangle>

        <TextBlock TextWrapping="Wrap" HorizontalAlignment="Stretch" Canvas.Top="17" Canvas.Left="45.348" Foreground="#FFFFFFFF" Text="{TemplateBinding Content}"/>

      </Canvas>

    </ControlTemplate>

  </UserControl.Resources>

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

      <controls:Label HorizontalAlignment="Left" VerticalAlignment="Top" BorderBrush="#FFFF0000" BorderThickness="10,0,5,0" Template="{StaticResource DenemeSablon}" Content="Tamamen Denemedir"/>

    </Grid>

</UserControl>

Yukarıdaki kodda özellikle önemli olan birkaç nokta var. İlk olarak nasıl olmuş da Label'ımız UserControl.Resources altındaki DenemeSablon adlı şablona bağlanmış? TemplateBinding'in kodu nasıl yazılmış? Tüm bunların cevaplarını kod içerisinde kalın yazılı bölümlerde bulabilirsiniz.

Label'a DataBinding nasıl yapılır?

Bir Label'e neden DataBind yapmak isteyelim? Sonuçta sadece Text göstermeyecek mi? Ve bu Text'in değişme şansı da yok ki TwoWayBinding vs gereksin? Tüm bu soruların cevabı aslında yukarıdaki ControlTemplating ile de alakalı. Bir Label düşünün ki kendisine Bind edilmiş nesneye göre şekil alabiliyor? Ne dersiniz?

Bir önceki örneğimizden devam edelim. Varsayalım ki Label'ımızda bir ürünün adını göstereceğiz fakat ürünün satış miktarına göre de Label'ın arkasında Gradient'ın (Aslında Rectangle) şeffaflaşmasını veya görünür olmasını istiyoruz. Bunun için ilk olarak gelin kontrolümüzün tasarımını biraz değiştirelim.

DataBind yapacağımız Label kontrolünün şablonunu biraz değiştirdik.
DataBind yapacağımız Label kontrolünün şablonunu biraz değiştirdik.

Sadece renklerde biraz değişiklik yaptık. Böylece arkadaki Rectangle tamamen şeffaf olsa da yazı görünebilecek. Şimdi geçelim kod tarafına ve bu Label'a nasıl veri bağlarız ona bakalım.

İlk olarak Label'a bağlayacağım Urun'ümüzün bir sınıf olarak programatik anlamda tanımlamamız gerekiyor.

[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 Double

        Public Property Satis() As Double

            Get

                Return PSatis

            End Get

            Set(ByVal value As Double)

                PSatis = value

            End Set

        End Property

 

    End Class

[C#]

    public class Urun

    {

        public string Adi { get; set; }

        public double Satis { get; set; }

    }

Gördüğünüz üzere Urun sınıfımızın iki Property'si var. Bunlardan ilki ürünün ismini saklayacak olan Adi, diğeri ise Satis miktarı. Özellikle Satis Property'sinin Double olarak tanımlandığına dikkat edelim. Herhangi bir Convertor kullanmadan bu Property'si Bind edeceğimiz için Opacity ile uyumlu şekilde 1 ile 0 arasında Double değerler taşımalı.

[VB]

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

        Etiket.DataContext = New Urun() With {.Adi = "Bir ürün adı", .Satis = 0.5}

    End Sub

[C#]

    private void Page_Loaded(object sender, System.Windows.RoutedEventArgs e)

    {

        Etiket.DataContext = new Urun { Adi = "Bir ürün adı", Satis = 0.5 };

    }

Kodumuzda basit bir şekilde yeni bir ürün yaratarak Etiket adındaki Label kontrolümüze DataContext özelliği üzerinden bağlıyoruz. Peki Adi ve Satis Property'leri Label içerisinde neleri etkileyecek? İşte bunun için ayrıca XAML tarafında ayarlar yapmamız gerek.

Rectangle'ın Opacity'sinin DataBinding ayarlarını yapıyoruz.
Rectangle'ın Opacity'sinin DataBinding ayarlarını yapıyoruz.

Blend tarafında Label kontrolünün şablonuna tekrar geri dönüyoruz. Daha önce yarattığımız ControlTemplate'i açarak üzerinde değişiklikler yapmamız gerekiyor. İlk olarak şablon içerisinde Rectangle'ı seçerek Properties tabından Opacity'sinin yanında ufak kareye tıklıyoruz ve gelen menüden "Custom Expression" komutunu seçiyoruz. Böylece artık binding ile ilgili ayarı doğrudan el ile yazacağız.

DataBinding için Custom Expression yazıyoruz.
DataBinding için Custom Expression yazıyoruz.

Yazdığımız Custom Expression ile artık Label kendi içindeki Rectangle'ın Opacity değerinin kendisine verilen datadan geleceğini ve bağlanması gereken Property'nin adının da Satis olduğunu biliyoru. Aynı işlemi ControlTemplate içerisindeki TextBlock için de yaparak bu sefer TextBlock'un Content özelliğini Adi Property'sine {Binding Adi} Custom Expression'ı ile bağlamamız gerek.

Tüm bu işlemleri yaptıktan sonra uygulamayı çalıştırdığınızda bağladığınız verideki ürün adının TextBlock içerisine yerleştiğini ve gelen satış bilgisine göre de arkadaki Rectangle'ın şeffaflığının belirlendiğini görebilirsiniz. Böylece gelen veriye göre görselliğini değiştiren bir Label tasarlamış olduk.

Hepinize kolay gelsin.