Silverlight 5 Beta'da Ancestor Relative Binding

0 dakikada yazıldı

12428 defa okundu

Düzenle

Geldik bir başka Silverlight 5 yeniliğine... WPF'ten bilenler yazıyı okuyarak işkence çekmesinler diye hemen söyleyelim Ancestor Relative Binding zaten WPF'te vardı. Silverlight 5 ile SL dünyasına da geliyor. Eğer WPF tarafından biliyorsanız zaten sorun yok.

Ancestor Relative Binding herhangi bir Binding işleminin nesnenin üst nesnelerine doğru yönlendirilebilmesini sağlıyor. Yani düşünün ki ListBox içerisindeki ItemTemplate'i değiştirdiniz fakat her ItemTemplate içerisinde bir kontrolün de gidip ListBox'dan birşey alması gerek, işte bu durumda Ancestor Binding işinizi kolaylaştırabiliyor. Özellikle Ancestor yani üst nesnelerin Runtime tarafından automated yaratıldığı senaryolarda bu nesnelerin propertylerine ulaşıp binding yapabiliyor olmak çok keyifli olabiliyor.

Değişik hareketler yapalım....

Aslında pek de değişik olmayacak :) yapacağımzı hareket çok basit bir hareket olacak. Şimdi diyelim ki bir DataGrid var elimizde ve hücrelerinden birinde de veya bir kolonunda da custom bir UserControl'ümüz var. Bu UserControl duruma göre DataGrid içerisinde bulunduğu satırın fon rengini değiştirebilmek istiyor. Günün sorusu geliyor : Bunu nasıl yaparız?

Aklınıza birçok çözüm gelebilir. Hatta düşündüklerinizi hemen yorum olarak bu yazıya atabilirseniz belki ilginç şeyler de çıkabilir. Benim aklıma ilk gelen DataGrid'in stilleri ile oynayıp stilleri override ederek stillerdeki bir özelliği binding aracalığı ile bir şekilde bizim kontrole kadar getirmek oldu. Fakat bu iş hiç de kolay olmayacak. Oysa :) Ancestor Relative Binding ile olay çok basit bir şekilde çözülebilir.

DataGrid içerisindeki her ColumnDefinition DataTemplate'i çalışma zamanında önce bir CellPresenter, sonra da CellsPresenter içerisine alınır. Bunu biz XAML içerisinde görmeyiz fakat on-thy-fly check ettiğimizde bu kontrolleri yakalayabiliriz. Tahmin edebileceğiniz üzere CellPresenter içerisinde bulunduğumuz hücreyi içerirken CellsPresenter ise birden çok CellPresenter içerir. Bizim de aslında satırın fon rengini değiştirmek için yapmamız gereken CellsPresenter'ın fon rengini değiştirmek olacak.

Gördüğünüz üzere ulaşmak istediğimiz kontrol runtime'da yaratılıyor ve aslında bizim DataTemplate içerisindeki kontrolümüzün çok üstünde. İşte tam da Ancestor Binding kullanmanın zamanı.

[XAML]

        \<sdk:DataGrid AutoGenerateColumns="true" Height="186" HorizontalAlignment="Left" \                     Margin="12,12,0,0" Name="dataGrid1" VerticalAlignment="Top" Width="376" >\             \<sdk:DataGrid.Columns>\                 \<sdk:DataGridTemplateColumn>\                     \<sdk:DataGridTemplateColumn.CellTemplate>\                         \<DataTemplate>\                                 \<Button Click="Button_Click" Tag="{Binding ???Nasıl bir binding olacak burada????}"  />\                         \DataTemplate\>\                     \sdk:DataGridTemplateColumn.CellTemplate\>\                 \sdk:DataGridTemplateColumn\>\             \sdk:DataGrid.Columns\>\         \sdk:DataGrid\>

Bir Ancestor Binding'in iki özelliği var. Bunlardan ilki AncestorType; yani Binding işleminin yapılabilmesi için aranan nesnenin tipi. Bizim senaryomuzda elimizde DataTemplate içerisinde bulunan basit Button kontrolünün Tag Property'sini bind eceğiz satırın fon rengine. O nedenle yukarıya doğru arama yaparaken bulmamız gereken nesnenin tipi DataGridCellsPresenter olacak. Bu nesne tipini XAML içerisinde tanımlayabilmek için bir XMLNS tanımlayacağız.

[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"\     xmlns:Primitives="clr-namespace:System.Windows.Controls.Primitives;assembly=System.Windows.Controls.Data"\     mc:Ignorable="d"\     d:DesignHeight="300" d:DesignWidth="400" \     xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"\>

Hedef tipimizi ayarladığımızda göre karar vermemiz gereken ikinci şey ise hedef nesnenin hangi Property'sini Button'un Tag'ına bind edeceğimiz. Satırın fon rengini değiştirmek istediğimize göre binding Path'imiz de Background olacak. Artık iki parametremiz de hazır. Button'dan yola çıkarak yukarı doğru gezip ilk DataGridCellsPresenter'ı bulup Background property'sini bizim Tag Property'sine bind etmemiz gerek.

[XAML]

\<Button Click="Button_Click" \   Tag="{Binding RelativeSource={RelativeSource AncestorType=Primitives:DataGridCellsPresenter}, \   Path=Background, Mode=TwoWay}"  />

Yukarıda gördüğünüz Binding Syntax'ı Ancestor Relative Binding olarak adlandırılıyor. RelativeSource özelliğini set ettiğimiz Binding kendisine verilen AncestorType'a göre tüm üst elementleri arayarak ilk karşılaştığının Path özelliği ile binding işlemini gerçekleştiriyor. Örnekte UserControl yerine ben basit bir Button kullanıp Click eventini de code behind'da bir methoda bağladım. Click eventinde basit bir şekilde Button'un Tag'ine atadığım SolidColorBrush binding sayesinde otomatik olarak DataGridCellsPresenter'ı Background 'una atanmış oluyor.

[C#]

        private void Button_Click(object sender, RoutedEventArgs e)\         {\             Button S = sender as Button;\             S.Tag = new SolidColorBrush(Colors.Red );\         }

Button yerine custom bir UserControl kullandığınızda kendi Custom Property'leriniz ile de bu işi yapabilirsiniz. Ancestor Relative Binding çoğu farkı mekanizması kolaylaştırabilir ve yaptığınız çoğu şey daha kolay yapmanızı sağlayabilir. Artık Silverilght 5 Beta ile aklımızda bulundurmamız gereken bir seçenek olarak kenara kaydetmek gerek ;)

Hepinize kolay gelsin.