Silverlight 5 Beta Markup Extensions

0 dakikada yazıldı

7742 defa okundu

Düzenle

XAML tarafındaki binding mekanizmalarını biliyoruz. Örneğin herhangi bir
property'yi XAML tarafında tanımlı bir nesnenin bir attribute'üne
bağlamak için aşağıdaki gibi basit bir binding syntaxi kullanabiliriz.

        <TextBox Text="{Binding Metin, Mode=TwoWay}" />

Peki ya bu yapıların yeterli gelmediği senaryolarda kendi yapılarımızı
tanımlama şansımız var mı? İşte tam da bu noktada Markup Extensions
Silverlight 5 Beta ile karşımıza çıkıyor. Çoğu zaman ViewModel'lerinizi
daha temiz tutabilmek ve olabildiğince View(XAML) ile ViewModel'i
birbirinden uzak tutabilmek adına kullanabileceğimiz Markup Extensions
özelliği gelin beraber inceleyelim.

Kendi extensionlarımızı yaratsak?

Kendi markup extension'ınızı yaratmanızı gerektirecek birçok senaryo ve
neden bulunabilir. Biz şimdilik ufak bir lokalizasyon örneği üzerinden
ilerleyelim. Böylece yapının nasıl çalıştığını ve implementasyonu
incelemiş oluruz. Sonrası artık sizin hayal gücünüze kalır ;)

Örneğimizde herhangi bir kontrole verilecek olan String değerin lokalize
olmasını sağlayacağız. Bu işlem Silverlight içerisinde farklı binding
yapıları ile yapılabilir fakat synaxti basitleştirmeyi düşünürsek
aşağıdaki gibi birşey hayal edebiliriz.

        <TextBox Text="{Lokalizasyon Anahtar=Metin, Varsayılan=Bulunamadı}" />

Hayat ne kadar güzel olurdu değil mi? XAML kodu ne kadar da temiz
gözüküyor :) Metin adında bir anahtarımız olduğunu ve anahtara denk
gelen metnin dil dosyalarından alınacak TextBox'ın Text değerine
verilmesi gerektiğini belirtmek keşke bu kadar kolay olsa. Diğer yandan
bir ikinci parametre olarak da Varsayılan değerimiz var. Eğer
lokalizasyon dosyalarında Metin anahtarı bulunamazsa bu değer
Textbox'a aktarılacak. Eh, gelin şimdi buna benzer birşey yapalım.

[VB]

Public Class Lokalizasyon
    Inherits Markup.MarkupExtension

    Public Property Anahtar As String
    Public Property Varsayilan As String

    Public Overrides Function ProvideValue(serviceProvider As System.IServiceProviderAs Object
        Dim Metin As String = MevcutDil.Bul(Anahtar)
        
If String.IsNullOrEmpty(Metin) Then
            Return Varsayilan
        
Else
            Return Metin
        
End If
    End Function
End Class

İlk olarak yukarıdaki kod içerisindeki renkli kısımlara bakalım. Apayrı
bir kod dosyası yaratarak projemize ekledikten sonra yeni bir sınıf
yaratıyoruz. Bu sınıfımızın MarkupExtensions'ın türüyor olması çok
önemli. Böylece kendi Markup Extension'ımızı yazabileceğiz. Sonrasında
hemen bu markupda kullanmak istediğimiz olası parametreleri
belirtiyoruz. Bizim örneğimizde Anahtar ve Varsayilan adında iki
tane parametre hayal etmiştik. Hemen onları birer String Property olarak
tanımlıyoruz.

[VB]

Public Class Lokalizasyon
    Inherits Markup.MarkupExtension

    Public Property Anahtar As String
    Public Property Varsayilan As String

    Public Overrides Function ProvideValue(serviceProvider As System.IServiceProviderAs Object
        Dim Metin As String = MevcutDil.Bul(Anahtar)
        If String.IsNullOrEmpty(Metin) Then
            Return Varsayilan
        Else
            Return Metin
        End If
    End Function
End Class

Gelelim can alıcı noktaya. Kendi markup extension'ımızı yaratabilmemiz
için bu extension'ın yapacağı şeyi de belirtmemiz gerek. Esas
işlevselliği kodlayacağımız yer ProvideValue metodu olacak. Bu
metodun içerisinde sınıfımızı gelen parametrelere göre gerekli kodları
yazarak geriye ne döndürmemiz gerektiğine karar verebiliyoruz.
Hatırlarsanız biz bir anahtara göre lokalizasyon dosyalarından metin
döndürecektik.

Bu noktada lokalizasyonu nasıl implemente ettiğiniz kısmına
bulaşmayacağız çünkü amacımız tam olarak o kısmı incelemek değil.
MevcutDil.Bul adında static/shared bir metoda anahtar göndererek o an
kullanıcının kullandığı dile göre metni aldığımızı düşünelim. Sonraki
adımda bu metnin boş olup olmadığını kontrol ediyoruz. Eğer metin boş
ise yapmamız gereken bize verilen Varsayilan parametresini geri
göndermek ki binding sonrasında o metin gözüksün.

Tüm bu kodlamayı bitirdikten sonra artık XAML tarafına geçebiliriz. İlk
Markup Extension'ımızı yazmış olduk. Sıra geldi onu kullanmaya. Bunun
için hemen bu sınıfı tanımladığımız assembly için bir XML namespace
tanımlayalım.

[XAML]

\\     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"\     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"\     mc:Ignorable="d"\              xmlns:daron="clr-namespace:SilverlightApplication4"\     d:DesignHeight="300" d:DesignWidth="400"\>

Yukarıdaki gibi istediğiniz bir isimle XML namespaceinizi tanımladıktan
sonra doğrudan bu namespace üzerinden markup extensionımızı binding
syntaxlarında kullanabiliriz.

[XAML]

    <Grid x:Name="LayoutRoot" Background="White">
        <TextBox Text="{daron:Lokalizasyon Anahtar=Metin, Varsayilan=Bulunamadi}" />
    </Grid>

Başta hayal ettiğimize çok yakın bir yazım şeklini yakalayabildik değil
mi? İşte MarkUp Extension bu işe yarıyor. Esasında ViewModel'in içinde
ayağı olacak bir işlemi dışarı çekerek XAML kodunu da daha temiz
tutabiliyoruz. Makrup Extension yapıları ile "Şunu da ben bunla yaparım"
:) dediğiniz şeyleri yorum olarak bekliyorum ;) Bakalım neler çıkacak.

Görüşmek üzere.