Makale Özeti

Silverlight Toolkit çok kısa süre önce stabil sürümleri ile yayınlandı. Bu yazımızda Silverlight 2.0 içerisinde Silverlight Toolkit kullanımına bir giriş yaparken Toolkit içerisinde TreeView kontrolünün kullanımını da inceliyoruz.

Makale

Silverlight 2.0 ile beraber gelen kontrol sayısı 1.0'a kıyasla ciddi miktarda arttı. Fakat hala eksikler var! İşte bu eksikleri Silverlight sürümleri arasında doldurabilmek adına yeni bir proje CodePlex üzerinde yayında. Proje aslında uzun süredir geliştiriliyor. Fakat daha yeni yeni stabil kontroller sunmaya başladı. Aslında eski AJAX Control Toolkit'e benzetebileceğimiz bir yapıda ilerleyen Silverlight Toolkit unutmamak gerek ki doğrudan Microsoft tarafından geliştirilmiyor, tamamen açık kaynak kodları ile gönüllü programcılar tarafından ilerletilen bu projede bazı kontroller stabil olarak işaretlenmişken bazıları ise hala "Preview" konumundalar.

İşte bu kütüphane içerisinde stabil olarak işaretlenmiş olan kontrollerden belki de en acil ihtiyaç duyacağımız TreeView kontrolünü bu yazımızda inceleyeceğiz.

Nasıl yüklenir?

Silverlight Toolkit içerisinde kontrollerden herhangi birini kullanabilmek için ilk olarak tabi ki söz konusu kütüphaneyi CodePlex üzerinden indirmeliyiz. Hemen aşağıdaki adresten son paketi indirebilirsiniz;

http://www.codeplex.com/Silverlight/Release/ProjectReleases.aspx?ReleaseId=18804

Paketi bilgisayarınıza indirdiğinizde Binaries klasörü içerisinde bulunan Microsoft.Windows.Controls.dll dosyasını yeni yarattığınız bir Silverlight projesine Visual Studio içerisinde referans olarak eklemeniz gerekiyor. Paket içerisinde bulunan diğer DLL'lere ve dosyalara ileriki makalelerimizde değineceğiz.

Unutmayın, referans ekleme işlemini doğrudan Silverlight projenize yapmanız gerek. Silverlight projenizle aynı Solution içerisinde bulunan ASP.NET proje ile herhangi bir ilişkimiz yok.

Bu işlemi tamamladıktan sonra artık Expression Blend tarafına geçerek kontrollerimizi kullanmaya başlayabiliriz. Eğer Expression Blend ile değil de Visual Studio tarafında XAML kodlarını yazmak isterseniz tek tek XAML içerisinde NameSpace tanımlarını yapmanız gerekecektir.

Expression Blend ile projemizi açtıktan sonra "Asset Library"e gidip "Custom Controls" tabına geçtiğimizde TreeView kontrolü karşımıza çıkıyor.

TreeView kontrolü Expression Blend içerisinde karşımıza çıkıyor!
TreeView kontrolü Expression Blend içerisinde karşımıza çıkıyor!

TreeView kontrolünü Blend içerisinde projenizde herhangi bir XAML dosyasına eklediğinizde XAML koduna dönüp bakarsanız aşağıdaki şekilde gerekli NameSpace tanımlarının da yapılmış olduğunu göreceksiniz. Eğer Blend kullanmasaydık bu işlemleri Visual Studio içerisinde elle yapmamız gerekecekti.

[XAML]

<UserControl x:Class="SilverlightApplication7.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:TreeView Margin="74,43,133,137"/>

 

    </Grid>

</UserControl>

Nasıl kullanılır?

Bir TreeView aslında birden çok TreeViewItem içerir. İsterseniz bu TreeViewItem'ları doğrudan Expression Blend içerisinde sürükle & bırak tekniği ile TreeView içerisine yerleştirebileceğiniz gibi isterseniz doğrudan kod ile databind işlemleri de yapabilirsiniz.

[XAML]

      <controls:TreeView Margin="74,43,133,137">

        <controls:TreeViewItem Header="Deneme1"/>

        <controls:TreeViewItem Header="Denem 2"/>

        <controls:TreeViewItem Header="Deneme 3">

          <controls:TreeViewItem Height="100" Width="100" Header="İçinde!"/>

        </controls:TreeViewItem>

      </controls:TreeView>

Yukarıdaki kod içerisinde birden çok TreeViewItem içeren bir TreeView görüyorsunuz. TreeView altında toplam üç adet TreeViewItem varken son TreeViewItem içerisinde bir tane daha TreeViewItem var. Böylece iç içe açılarak devam eden sonsüz döngüde bir ağaç yapısı oluşturmak mümkün.

TreeViewItem'ların Header özelliğine gözükecek metin değerini girebileceğiniz gibi aslında farklı Silverlight kontrollerini de Header içerisine koyma şansınız var.

[XAML]

      <controls:TreeView Margin="74,43,133,137">

        <controls:TreeViewItem Header="Deneme1"/>

        <controls:TreeViewItem Header="Denem 2"/>

        <controls:TreeViewItem Header="Deneme 3">

        <controls:TreeViewItem Height="100"

                              Width="100">

          <controls:TreeViewItem.Header>

            <Image Height="50"

                  Width="50"

                  Source="Tree.jpg" />

          </controls:TreeViewItem.Header>

        </controls:TreeViewItem>

        </controls:TreeViewItem>

      </controls:TreeView>

Yukarıdaki kod içerisinde de görebileceğiniz gibi TreeViewItem'lardan birinin Header'ında bir Image nesnesi, yani fotoğraf var. Siz uygulamalarınızda farklı fantaziler yaparak isterseniz MediaElement aracılığı ile video bile koyabilir veya belki de TreeView içerisine bir DataGrid veya Calendar bile koyabilirsiniz.

Gelelim tüm bu işlemlerin kod ile nasıl yapıldığına. Varsayalım elimizde TreeView'de göstermek istediğimiz bir veri var. İlk olarak bu veriyi uygun şekilde düzenlememiz gerek. Bizim örneğimizde Fiyati ve Adi gibi özelliklere sahip bir sınıf kullanalım. Her bir TreeViewItem bu sınıf üzerinden oluşturulacak.

[VB]

    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 PFiyati As Integer

        Public Property Fiyati() As Integer

            Get

                Return PFiyati

            End Get

            Set(ByVal value As Integer)

                PFiyati = value

            End Set

        End Property

 

        Private PList As List(Of Urun)

        Public Property Liste() As List(Of Urun)

            Get

                Return PList

            End Get

            Set(ByVal value As List(Of Urun))

                PList = value

            End Set

        End Property

 

        Public Sub New()

            Me.PList = New List(Of Urun)

        End Sub

    End Class

[C#]

        public class Urun

        {

            public string Adi { get; set; }

            public int Fiyati { get; set; }

            public List<Urun> Liste { get; set; }

 

            public Urun()

            {

                this.Liste = new List<Urun>();

            }

        }

Gördüğünüz gibi sınıfımızın Adi ve Fiyati özellikleri haricinde bir de List tipinden Liste adında Property'si var. Bunun nedeni aslında çok basit. Her bir TreeViewItem'ın kendi içinde birden çok TreeViewItem olabilir demiştik. Bizim her bir ürünümüzün için de bu şekilde birden çok ürün saklanabiliyor olacak. Verimizi bu şekilde üretip TreeView'e DataBind ettiğimizde TreeView geri kalanı halledecek.

Gelin şimdi de bizim için deneme amaçlı olarak geçici veri yığını yaratacak bir kod yazalım.

[VB]

    Function Veriyarat() As List(Of Urun)

        Dim Liste As New List(Of Urun)

        For x As Integer = 0 To 10

            Dim BirUrun = New Urun With {.Adi = "Ürün" & x, .Fiyati = Rnd() * 1000}

            For y As Integer = 0 To 5

                BirUrun.Liste.Add(New Urun With {.Adi = "Ürün" & y, .Fiyati = Rnd() * 1000})

            Next

            Liste.Add(BirUrun)

        Next

        Return Liste

    End Function

[C#]

       public List<Urun> Veriyarat()

        {

            Random RastGele = new Random();

            List<Urun> Liste = new List<Urun>();

            for (int x = 0; x <= 10; x++) {

                Urun BirUrun = new Urun { Adi = "Ürün" + x.ToString(), Fiyati = RastGele.Next(0,1000) };

                for (int y = 0; y <= 5; y++) {

                    BirUrun.Liste.Add(new Urun { Adi = "Ürün" + y.ToString(), Fiyati = RastGele.Next(0, 1000) });

                }

                Liste.Add(BirUrun);

            }

            return Liste;

        }

Kodumuz içerisinde toplam 10 adet içerisinde 5'er ürün bulunan ürün yaratılıyor. Şimdi tüm bu listeyi alarak doğrudan TreeView'ın ItemsSource özelliğine aktaracağız. Siz örneklerinizde farklı sınıflar ve farklı veri kaynakları kullanabilirsiniz. Özellikle LINQ2SQL veya Data Services kullandığınızı düşünürsek zaten elinize bu şekilde hazır nesneler gelecektir.

[VB]

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

        Agac.ItemsSource = Veriyarat()

    End Sub

[C#]

        public Page()

        {

            InitializeComponent();

            this.Loaded += new RoutedEventHandler(Page_Loaded);

        }

 

        void Page_Loaded(object sender, RoutedEventArgs e)

        {

            Agac.ItemsSource = Veriyarat();

        }

Veri bağlantımızı yaptık. Fakat bu TreeViewItem'lar nasıl yaratılacak? Fiyati ve Adi adındaki özelliklerin içindeki değerler nerede gösterilecek? İşte bu noktada XAML tarafına geçerek bir ItemTemplate düzenlememiz gerekiyor. Böylece TreeView kendisine bağlanan veriye göre TreeViewItem'lar yaratırken nasıl bir görsellikten yola çıkacağını ve bu görsellik içerisinde gelen veriden hangi değerlerin nerelere yerleştirileceğini anlayabilecek.

[XAML]

    <controls:TreeView Margin="74,43,133,137"

                      x:Name="Agac">

      <controls:TreeView.ItemTemplate>

        <controls:HierarchicalDataTemplate ItemsSource="{Binding Liste}">

          <StackPanel Orientation="Horizontal">

            <TextBlock Text="{Binding Adi}"

                      Margin="5,0,0,0"

                      HorizontalAlignment="Left"

                      FontSize="10" />

            <TextBlock Text="{Binding Fiyati}"

                      Margin="5,0,0,0"

                      HorizontalAlignment="Left"

                      FontSize="10" />

          </StackPanel>

        </controls:HierarchicalDataTemplate>

      </controls:TreeView.ItemTemplate>

    </controls:TreeView>

Yukarıdaki XAML kodu ile aslında uygulamamızı sonlandırmış olduk. Peki neler yaptık? İlk olarak TreeView'ın ItemTemplate'i içerisinde yine Toolkit içerisinden gelen HierarchicalDataTemplate nesnesini yerleştirdik. Bu nesne bizim kod tarafında yarattığımız nested yapıyı algılayarak iç içe TreeViewItem'ların yaratılmasını sağlayacak fakat DataBind yaptığımız sınıfların hangi Property'sinin başka nested TreeViewItem'ların verilerini sakladığını anlayabilmesi için söz konusu Property'nin adını vermemiz lazım. Hatırlarsanız bizde Urun sınıfının Liste adında bir property'si vardı ve tüm alt öğeleri o saklıyordu. Biz de burada HierarchicalDataTemplate 'e ItemsSource olarak Liste'yi Bind ediyoruz. Geri kalanı kendisi halledecektir.

HierarchicalDataTemplate içerisinde doğrudan her bir TreeViewItem'ın Header bilgisini girer gibi istediğiniz Silverlight kontrollerini kullanabiliyorsunuz. Burada yapacağınız tasarım her TreeViewItem için kullanılacaktır. Tabi bunu yaparken Binding'lerimizi de unutmuyoruz ve yerine göre Fiyati ve Adi özelliklerini istediğimiz kontrollerin istediğimiz özelliklerine Bind ediyoruz. Bizim örneğimizde bir StackPanel içerisinde Fiyati ve Adi özelliklerini gösterecek iki farklı TextBlock bulunuyor.

DataBind TreeView örneğimiz bitti.
DataBind TreeView örneğimiz bitti.

Tüm verimizi bağladığımıza göre yeri geldiğinde seçili öğeyi nasıl yakalarız? Her bir TreeView'ın kendi SelectedItemChanged event'ı var. Bu event çalıştığında söz konusu TreeView'ın SelectedItem özelliğinden seçili öğeyi alabilirsiniz. En önemlisi SelectedItem size aslında DataBind esnasında bağlanan verinin içerisinde bulunan nesneyi döndürüyor. Yani bizim örneğimizde SelectedItem'ı aldığımda elimize Urun tipinden bir nesne gelecek. Gönül daha ne ister? :)

Hepinize kolay gelsin.