Silverlight 5 Beta'da Implicit Data Templates

0 dakikada yazıldı

10889 defa okundu

Düzenle

Silverlight 5 Beta ile beraber gelen yeni özelliklerden biri de Implicit Data Templates. Özelliğin güzelliğine gelmeden önce :) biraz elimizde neler var ona bakalım.

Malum ListBox gibi kontrollerin ItemTemplate'ini özelleştirebiliyoruz. ItemTemplate kabaca kontrol içerisinde kontrole vereceğimiz nesne listesindeki her nesneyi görsel olarak temsil edecek olan görsel tasarımı tanımlıyor.

[XAML]

     \<ListBox x:Name="list_Mesajlar" HorizontalAlignment="Left" Margin="24,18,0,17" \     Width="131" ItemTemplate="{StaticResource DataTemplate1}"/>

ItemTemplate editleme işlemini Expression Blend ile yaparsak Blend otomatik olarak bir DataTemplate'i kontrolün Resources kolleksiyonuna koyarak DataTemplate'e verdiğimiz ismi direk ListBox'ın ItemTemplate özelliğine atıyor.

[XAML]

\<DataTemplate x:Key="DataTemplate1">\   \<StackPanel d:DesignWidth="318" d:DesignHeight="108">\     \<StackPanel Orientation="Horizontal">\       \<TextBlock TextWrapping="Wrap" Text="Gönderen:" Foreground="#FF3F3F3F"/>\       \<TextBlock TextWrapping="Wrap" Text="{Binding GonderenAdi}"/>\     \StackPanel\>\     \<StackPanel Orientation="Horizontal">\       \<TextBlock TextWrapping="Wrap" Text="Alan:" Foreground="#FF3F3F3F"/>\       \<TextBlock TextWrapping="Wrap" Text="{Binding AlanAdi}"/>\     \StackPanel\>\     \<TextBlock TextWrapping="Wrap" Text="Mesaj:" Foreground="#FF3F3F3F"/>\     \<TextBlock TextWrapping="Wrap" Text="{Binding Metin}"/>\   \StackPanel\>\ \DataTemplate\>

Yukarıdaki gördüğünüz basit bir DataTemplate. Tahmin edebileceğiniz üzere AlanAdi, GonderenAdi ve Metin gibi Property'leri ile nesnelerden oluşan bir kolleksiyonu göstermek için yaratılmış durumda. Şimdi bir de kod tarafına göz atalım.

[C#]

        public class Mesaj\         {\             public string Metin { getset; }\         }\         public class Mail : Mesaj \         {\             public string GonderenMail { getset; }\             public string GonderenAdi { getset; }\             public string AlanMail { getset; }\             public string AlanAdi { getset; }\         }\         public class SMS : Mesaj \         {\             public string GonderenNumara { getset; }\             public string AlanNumara { getset; }\         }

Kodumuz içerisinde iki tip mesajımız var. SMS ve Mail adındaki bu mesaj tipindeki nesneler Mesaj adında bir başka nesneden türetilmiştir. Bizim istediğimiz ise tüm bu nesneleri alıp topluca ListBox'da gösterebilmek ve duruma göre de eğer elde Mail varsa farklı bir DataTemplate, SMS varsa farklı bir tasarım kullanmak.

Karşınızda Implicit Data Templates

Biraz önce karşılaştığımız sorunu çözebilmek için Implicit Data Template kullanmamız şart. Peki nasıl olacak? İlk olarak elimizdeki Mesaj listesini gönül rahatlığı ile ListBox'ın ItemsSource'una vereceğiz. Listemizde Mail ve SMS'ler karşılık olarak duracaklar. Herhangi bir sorun yok. DataTemplate'ler konusuna gelince ise ilk olarak Key ile DataTemplate'i ListBox'a bağlamaktan vazgeçeceğiz. Sonra ise her DataTemplate'e hangi tür veriyi göstereceklerine dair gerekli bilgiyi vermemiz gerekecek.

[XAML]

\<UserControl.Resources>\   \<DataTemplateDataType="daron:Mesaj">\     \<StackPanel d:DesignWidth="318" d:DesignHeight="108">\       \<StackPanel Orientation="Horizontal">\         \<TextBlock TextWrapping="Wrap" Text="Gönderen:" Foreground="#FF3F3F3F"/>\         \<TextBlock TextWrapping="Wrap" Text="{Binding GonderenAdi}"/>\       \StackPanel\>\       \<StackPanel Orientation="Horizontal">\         \<TextBlock TextWrapping="Wrap" Text="Alan:" Foreground="#FF3F3F3F"/>\         \<TextBlock TextWrapping="Wrap" Text="{Binding AlanAdi}"/>\       \StackPanel\>\       \<TextBlock TextWrapping="Wrap" Text="Mesaj:" Foreground="#FF3F3F3F"/>\       \<TextBlock TextWrapping="Wrap" Text="{Binding Metin}"/>\     \StackPanel\>\   \DataTemplate\>\   \<DataTemplate DataType="daron:SMS*">\     \<StackPanel d:DesignWidth="318" d:DesignHeight="108">\       \<StackPanel Orientation="Horizontal">\         \<TextBlock TextWrapping="Wrap" Text="Gönderen:" Foreground="#FF3F3F3F"/>\         \<TextBlock TextWrapping="Wrap" Text="{Binding GonderenNumara}"/>\       \StackPanel\>\       \<StackPanel Orientation="Horizontal">\         \<TextBlock TextWrapping="Wrap" Text="Alan:" Foreground="#FF3F3F3F"/>\         \<TextBlock TextWrapping="Wrap" Text="{Binding AlanNumara}"/>\       \StackPanel\>\       \<TextBlock TextWrapping="Wrap" Text="Mesaj:" Foreground="#FF3F3F3F"/>\       \<TextBlock TextWrapping="Wrap" Text="{Binding Metin}"/>\     \StackPanel\>\   \DataTemplate\>\ \UserControl.Resources\>

Yukarıda iki farklı DataTemplate görüyorsunuz. DataType özelliklerinden de anlayabileceğiniz bu arkadaşlar iki farklı nesne tipini hedefliyorlar. Bu arada tabi C# kodunda tanımladığım nesneleri XAML'a alabilmek için XML NameSpace tanımımızı da koymayı unutmamalıyı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:daron="clr-namespace:SilverlightApplication10"\     mc:Ignorable="d"\     d:DesignHeight="300" d:DesignWidth="400"\>

Bu şekli ile örneği çalıştırdığınızda ListBox'a verdiğiniz farklı mesajlardan, yani SMS ve Mail'lerden oluşan listenin başarılı bir şekilde ListBox tarafından gösterildiğini göreceksiniz. Listedeki her SMS için uygun SMS'lere bağladığımız DataTemplate her Mail için de Mail nesnesi ile eşleştirdiğimiz DataTemplate kullanılıyor olacak.

Sorun olabilir!

Diyelim ki aynı UserControl içerisinde bir de Combobox var ve şansa bakın ki Combobox'da Mail veya SMS tipinde nesneler gösteriyor :) İşte dağıldığımız noktadır :) DataTemplate'ler ayrı ayrı isimlerle ListBox'a bağlamadığımız ve bir anlamda ortada bıraktığımız için Combobox da aynı DataTemplate'leri kullanacak.

Ortalık karışmış gibi
duruyor...Ortalık karışmış gibi duruyor...

Bu durumu engellemenin yolu DataTemplate'leri doğrudan ListBox'ın içine gömmek. Böylece bu DataTemplate'ler sadece o ListBox için geçerli olacaktır.

[XAML]

        \<ListBox x:Name="list_Mesajlar" \                  Margin="24,18,119,17">\      *       \<ListBox.Resources>\                 \<DataTemplate DataType="daron:Mesaj">\                     \<StackPanel d:DesignWidth="318" d:DesignHeight="108">\                         \<StackPanel Orientation="Horizontal">\                             \<TextBlock TextWrapping="Wrap" Text="Gönderen:" Foreground="#FF3F3F3F"/>\                             \<TextBlock TextWrapping="Wrap" Text="{Binding GonderenAdi}"/>\                         \StackPanel\>\                         \<StackPanel Orientation="Horizontal">\                             \<TextBlock TextWrapping="Wrap" Text="Alan:" Foreground="#FF3F3F3F"/>\                             \<TextBlock TextWrapping="Wrap" Text="{Binding AlanAdi}"/>\                         \StackPanel\>\                         \<TextBlock TextWrapping="Wrap" Text="Mesaj:" Foreground="#FF3F3F3F"/>\                         \<TextBlock TextWrapping="Wrap" Text="{Binding Metin}"/>\                     \StackPanel\>\                 \DataTemplate\>\                 \<DataTemplate DataType="daron:SMS">\                     \<StackPanel d:DesignWidth="318" d:DesignHeight="108">\                         \<StackPanel Orientation="Horizontal">\                             \<TextBlock TextWrapping="Wrap" Text="Gönderen:" Foreground="#FF3F3F3F"/>\                             \<TextBlock TextWrapping="Wrap" Text="{Binding GonderenNumara}"/>\                         \StackPanel\>\                         \<StackPanel Orientation="Horizontal">\                             \<TextBlock TextWrapping="Wrap" Text="Alan:" Foreground="#FF3F3F3F"/>\                             \<TextBlock TextWrapping="Wrap" Text="{Binding AlanNumara}"/>\                         \StackPanel\>\                         \<TextBlock TextWrapping="Wrap" Text="Mesaj:" Foreground="#FF3F3F3F"/>\                         \<TextBlock TextWrapping="Wrap" Text="{Binding Metin}"/>\                     \StackPanel\>\                 \DataTemplate\>\         *    **\**ListBox.Resources**\>\         \ListBox\>

Normalde bir DataTemplate'i ListBox'ın içine gömmek için Listbox.ItemTemplate diyerek bir XML elementi açar ve aslında hem Resource'u ListBox içine koymuş hem de gerekli Property'si set etmiş olurduk. Bu sefer birden çok DataTemplate olacağı için hepsini alıp Resource olarak ListBox'ın içine koyuyoruz. ListBox yine her zamanki gibi DataType'ın göre uygun Template'i seçerken ekrandaki diğer hiçbir kontrol bu DataTemplate'lere ulaşamayacaktır.

Hepinize kolay gelsin ;)