Silverlight 3.0 Beta içerisinde Element Binding ve IValueConverter

0 dakikada yazıldı

6219 defa okundu

Düzenle

Bu makalemizde aslında uzun zamandır WPF tarafında bulunan fakat
Silverlight 2.0'da olmayan bir özellikten bahsedeceğiz. Tabi bu
özellikten bahsetmemizin nedeni ise artık Silverlight 3.0 ile söz konusu
özelliği kullanabiliyor olmamız. Bahsettiğimiz özellik Element Binding
özelliği. Element Binding'i kabaca bir kontrolün herhangi bir
özelliğinin otomatik olarak başka bir kontrolün bir özelliğine
bağlanması ve aradaki değer değişikliklerinin karşı tarafa otomatik
olarak aktarılması şeklinde tanımlayabiliriz.

[XAML]

        <StackPanel>

            <TextBox
x
:Name="BirTextBox" ></TextBox>

            <Slider

               x:Name="BirSlider"></Slider>

        </StackPanel>

Ekranımızda yukarıdaki şekli ile bir TextBox ve bir de Slider
kontrolü olduğunu düşünelim. İstediğimiz şey bu Slider kontrolündeki
değerin sürekli olarak TextBox içerisinde gösterilmesi. Normal şartlarda
böyle bir işlevsellik için basit bir şekilde Slider'ın ValueChanged
durumunu yakalayıp sürekli olarak Slider'ın Value özelliğinden değer
alıp, bunu da String'e çevirip TextBox'ın Text değerine
eşitleyebilirdik. Eğer bu eşitlemenin çift taraflı olmasını istiyorsanız
farklı taklalar ile TextBox'ın da TextChanged durumunu yakalayıp
Slider'ın Value değerinin değiştirmeniz gerekecektir. Sonuç olarak her
iki kontrolden birinde kullanıcı bir değişiklik yaptığında diğerine
yansıyacak. Ama bu kadar kod yazmaktansa artık Binding tanımlayarak
hızlıca ilerleyebiliyoruz.

[XAML]

        <StackPanel>

            <TextBox
Text
="{Binding
Value
, ElementName=BirSlider}" ></TextBox>

            <Slider

               x:Name="BirSlider"></Slider>

        </StackPanel>

Artık TextBox'ımızın Text özelliğine farklı bir değer veriyoruz. Bu
değer özünde bir Binding nesnesi. Binding'imizi tanımlarken
hedeflediğimiz Property olarak Value ve bu Property'nin
alınacağı yer olarak da BirSlider adındaki Slider kontrolümüzü
gösteriyoruz. Bu noktadan sonra projeyi çalıştırdığımızda Slider
içerisinde kullanıcı tarafından bir değişiklik yapıldığında otomatik
olarak TextBox'ın Text'inin de güncellendiğini görebiliriz. Oysa teknik
açıdan baktığımızda birbirine Bind ettiğimiz Property'ler olan Text
ve Value Property'lerinin tipleri farklı. Value bir Double
olarak gelirken Text ise String olarak geliyor. Binding esnasında
buna rağmen bir sorun yaşamıyoruz.

Diğer yandan eğer TextBox içerisindeki sayısal değeri el ile
değiştirirsek bu değerin Slider'a yansımadığını görüyoruz. Bu sorunu
halledebilmek için Binding tanımlarken özellikle Binding işleminin çift
taraflı olarak yapılacağını da belirtmemiz gerekecek.

[XAML]

        <StackPanel>

            <TextBox

               Text="{Binding
Value
, ElementName=BirSlider,
Mode
=TwoWay}"></TextBox>

            <Slider

               x:Name="BirSlider"></Slider>

        </StackPanel>

Kod içerisinde de gördüğünüz üzere artık Binding'imizin modunu
TwoWay olarak değiştirdik. Sonuç olarak kullanıcı TextBox içerisine
sayısal bir değer girdiğinde bu değer otomatik olarak Slider'ın da Value
özelliğine aktarılacaktır.

Peki ya bind edilecek tipler tutmazsa?

Eğer birbirine bind etmek istediğiniz Property'lerin tamamen birbiri ile
alakasız ise bu sefer de Binding esnasında Converter yapılarını
kullanabilirsiniz. IValueConverter arayüzünü implemente eden bir sınıf
yaratıp rahatlıkla Binding esnasında gelen ve giden veriye müdahale
edebilirsiniz.

Örneğin gelin bir Slider'ın Value'su ile bir Calendar kontrolünün
SelectedDate özelliğini birbirine bağlamaya çalışalım. Normal
şartlarda DateTime ile Double'ı birbirine bağlayamazsınız ayrıca
Slider'ın başlangıç ve son değerleri yine birer Double iken belki biz
farklı başlangıç ve son tarihleri arasında Slider'ın çalışmasını
isteyeceğiz. İşte tam da bu noktada Sliderdan gelen değerleri birer
tarih eşleştirirsek Calendar için de anlamlı bir veri kaynağı
yaratmış oluruz.

[VB]

Public Class Cevirici

    Implements Data.IValueConverter

 

    Public Function Convert(ByVal value As Object,
ByVal targetType As System.Type, ByVal parameter As Object,
ByVal culture As System.Globalization.CultureInfo) As Object
Implements
System.Windows.Data.IValueConverter.Convert

        Return Now.Date.AddDays(value)

    End Function

 

    Public Function ConvertBack(ByVal value As Object,
ByVal targetType As System.Type, ByVal parameter As Object,
ByVal culture As System.Globalization.CultureInfo) As Object
Implements
System.Windows.Data.IValueConverter.ConvertBack

        Return CType(value, Date).Subtract(Now).TotalDays + 1

    End Function

End Class

[C#]

    public class Cevirici : System.Windows.Data.IValueConverter

    {

        public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)

        {

            return DateTime.Now.Date.AddDays((double)value);

        }

 

        public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)

        {

            return ((System.DateTime)value).Subtract(DateTime.Now).TotalDays + 1;

        }

    }

Yukarıda gördüğünüz Cevirici sınıfı IValueConverter arayüzünü
implemente ettiği anda Convert ve ConvertBack metodlarına da
sahip oluyor. Bu metodlar Binding esnasında gelen ve giden verinin
farklı tiplere çevrimi için kullanılabilir. Bizim örneğimizde Convert
metoduna gelen Double değerlerini o anki tarihe gün olarak
ekliyoruz. Böylece Slider'dan 2 değeri geldiğinde aslında Calendar
kontrolüne de bugünden 2 gün sonrasına ait tarihi vermiş oluyoruz. Eğer
Calendar içerisinde bir seçim yapıldığında Slider'a da
yansımasını istiyorsanız ConvertBack metodunu da yazmanız gerekiyor.
Bu metoda da Calendar'dan SelectedDate geleceği için o anki tarih
ile farkını bulup geri döndüyüroz.

[XAML]

<UserControl

   xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"

   x:Class="SilverlightApplication27.MainPage"

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

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

   xmlns:daron="clr-namespace:SilverlightApplication27"

   Width="400"

   Height="300">

    <UserControl.Resources>

        <daron:Cevirici

           x:Name="BirCevirici" />

    </UserControl.Resources>

    <Grid

       x:Name="LayoutRoot"

       Background="White">

        <StackPanel>

            <controls:Calendar

               SelectedDate="{Binding
Value
,

                              
ElementName
=BirSlider,

                              
Converter
={StaticResource
BirCevirici
},

                              
Mode
=TwoWay}"></controls:Calendar>

            <Slider

               x:Name="BirSlider"

               SmallChange="1"

               LargeChange="1"></Slider>

        </StackPanel>

    </Grid>

</UserControl>

Kod tarafında hazırladığımız Converter'ımızı XAML tarafında
kullanabilmek için hemen daron adında bir XAML namespace'i tanımladım ve
çalıştığım projenin Assembly'sine bağladım. Böylece söz konusu Assembly
içerisindeki kontrolleri XAML tarafında kullanabileceğiz. Bir sonraki
adımda kod tarafındaki Cevirici tanımından bir kopyayı
UserControl'un Resource'larına alıyorum ve adını da BirCeviri
koyuyorum. Artık BirCeviri nesnemizi Converter olarak istediğimiz
Binding'lerde kullanabiliriz. Kendi Binding tanımımıza bu bilgiyi de
ekledik mi işlem tamamdır. Unutmadan Binding'in modunu da TwoWay
olarak ayarlayalım.

İşte bu kadar!

Gördüğünüz gibi kontrollerin farklı özelliklerini rahatlıkla
birbirlerine gerektiğinde çift yönlü olarak da bağlayabiliyoruz. Bu
bağlama işlemi esnasında çok farklı çeviri ve kontrol mekanizmaları
oluşturabileceğimiz ValueConverter yapısına da göz attığımıza göre bir
makalemizin daha sonuna geldik.

Hepinize kolay gelsin.