TreeView kontrolünde drag-drop işlemi

Merhaba dostlar.

Bazı Windows uygulamalarında, kontroller arası sürükle-bırak işlemlerini kullanmamız gerekebilir. Birazdan yapacağımız uygulamada, söz konusu işlemi TreeView kontrolleri arasında yapacağız. Öncelikle aşağıdaki formu tasarlayarak işe başlayalım:

 

Burada amacımızı bir kez daha belirtelim; her iki TreeView kontrolünden de birbirlerine, sürükle-bırak işlemi ile TreeNode nesnesi taşımak. Bu taşıma sonrasında, sürükleme işlemini başlattığım TreeView kontrolünden, sürüklenen TreeNode nesnesini kaldırmak.

 

Uygulamamızın koduna geçmeden önce, her iki TreeView kontrolünün bazı özelliklerini ayarlayalım. Bunlardan biri; sürükle-bırak işlemi için olmazsa olmaz özellik olan AllowDrop özelliğini true yapmak. Diğeri ise, HideSelection özelliğini false yapmak. Peki acaba ne işe yarıyor şu HideSelection özelliği ve niye false yapmak durumundayım? Bir TreeView kontrolü içinde yer alan TreeNode nesnesine fare ile tıklayarak seçim yaptığınızda, bu TreeNode’a TreeView.SelectedNode özelliği ile ulaşabilirsiniz. Peki; seçimi yaptıktan sonra, başka bir kontrole fokuslanırsanız ne olur? Eğer, HideSelection özelliği true ise (ki varsayılan değeri true’dur), TreeView.SelectedNode özelliği boşalır (null). İşte biz bunu kesinlikle istemiyoruz. Çünkü, sürükleme işlemi esnasında, sürüklemeye başladığınız kontrolden, hedef kontrole geçtiğinizde, hedef kontrole fokuslanmış olursunuz. Haliyle, seçtiğimiz TreeNode nesnesine TreeView.SelectedNode ile ulaşacağımıza göre, HideSelection özelliğini false yapıyoruz.

Yine Koda geçmeden önce, bir şeyi daha belirtmeliyim; uygulamamızda, amacımız her iki TreeView kontrolünden birbirlerine sürükle-bırak işlemi yapmak. Bu nedenle bu uygulamada kullanılan olaylar, iki TreeView kontrolününün de ortak olaylarıdır.

Bu temel bilgileri verdikten sonra kodumuza geçebiliriz:

//sürüklenen treeNode nesnesinin hangi treeView kontrolünde bulunduğunu tutan bir treeView nesnesini global tanımlıyorum:

   TreeView dugumKaynagi = null;

   private void tree_MouseDown(object sender, MouseEventArgs e)

   {

      //Önce hangi treeView kontrolüne tıklanmış ona bakalım:

      TreeView tree = sender as TreeView;

      //şimdi de, hangi TreeNode’un seçilmiş olduğunu görelim:

      TreeNode dugum = tree.GetNodeAt(e.X, e.Y);

      tree.SelectedNode = dugum;

      //Bu TreeNode nesnesinin bulunduğu treeView, daha önce tanımladığımız dugumKaynagi değil midir?

      dugumKaynagi = dugum.TreeView ;

      //eğer dugum nesnesi boş değilse:

      if (dugum != null)

      {

         //Drag-Drop işlemini yap:

         tree.DoDragDrop(dugum, DragDropEffects.Copy );

      }

   }

Yukarıdaki metod, treeView kontrolünün MouseDown olayının tetiklenmesi sonucu çalışacak olan metodtur. Bu metodda, sürüklenecek olan TreeNode nesnesi belirlenmektedir. Dikkat ederseniz, bunu yapabilmek için TreeView.GetNodeAt() metodunu kullanıyoruz. Buradaki amaç şu; treeView’in MouseDown olayı tetiklendiği anda fare işaretçisinin altında bulunan TreeNode nesnesini seçili hale getirmek. Peki ya o sırada fare işaretçisinin altında bir TreeNode yoksa? Bunu da basit bir if yapısıyla (eğer düğüm nesnesi boş değilse) kontrol ediyoruz ve yanıt olumlu ise TreeView.DoDragDrop metoduyla TreeNode sürükleneceğini belirtiyoruz.

   private void tree_DragOver(object sender, DragEventArgs e)

   {

      TreeView tree = sender as TreeView;

      //başlangıçta, drag ve drop işlemi olmasın:

      e.Effect = DragDropEffects.None;

      //acaba sürüklenen data bir TreeNode nesnesi mi?

      if (e.Data.GetData(typeof(TreeNode)) != null)

      {

         if (dugumKaynagi != tree)

         {

             //Ekran koordinatını al:

             Point pt = new Point(e.X, e.Y);

             //bu koordinatı, treeView’in koordinat sistemine çevir.

             pt = tree.PointToClient(pt);

             //Mouse, bir düğümün üzerinde mi ?

             TreeNode dugum = tree.GetNodeAt(pt);

             if (dugum != null)

             {

                 //Eğer öyleyse, drag-drop efekti kopyalama olsun:

                 e.Effect = DragDropEffects.Copy ;

                 //ve hedef TreeView’in seçili düğümü, bizim koordinattaki dugum isimli TreeNode nesnesi oluversin:

                 tree.SelectedNode = dugum;

               }

            }

         }

      }

Tree_DragOver ise, sürükleme işlemi bitip, brakma işlemi gerçekleşirken tetiklenen DragOver olayının yakalayıcısıdır. Burada kontrol etmemiz gereken iki şey var. Birincisi, acaba sürüklenen nesne bir TreeNode mu ikincisi ise, bu treeNode başka bir TreeView kontrolünden mi geliyor? Eğer her iki önerme de true döndürürse, o zaman sürüklenen TreeNode nesnesini hedef TreeView kontrolüne yerleştirmek için kolları sıvıyoruz.

Peki ama, TreeNode nesnesi TreeView kontolünde NEREYE yerleşecek? Bunu yapabilmek için, “bırakma” olayı gerçekleşirken fare işaretçisinin “ekranın” neresinde olduğuna bakıyorum. Fakat ekranın koordinat sistemi ile treeView’in koordinat sistemi farklıdır. Bu fark da, çok temeldir aslında. Ekranın koordinat sistemi, monitörün sol üst köşesini 0 olarak baz alırken; treeView, kontrolün sol üst köşesini 0 merkezi olarak görür. Bu sebepten dolayı, TreeView.PointToClient() metodunu kullanarak koordinatları birbirine çeviriyorum. Böylece, treeNode nesnemi, hedef kontrolde bulunan node’a taşıyabiliyorum.

   private void tree_DragDrop(object sender, DragEventArgs e)

   {

      TreeView tree = (TreeView)sender;

      //Mouse’un koordinatını al:

       Point pt = new Point(e.X, e.Y);

      //Bu koordinat noktasını, treeView’in koordinat noktasına çevir.

      pt = tree.PointToClient(pt);

      //mouse’un üzerinde olduğu TreeNode nesnesini al:

      TreeNode node = tree.GetNodeAt(pt);

      TreeNode suruklenenNode = (TreeNode)e.Data.GetData(typeof(TreeNode));

      node.Nodes.Add((TreeNode)suruklenenNode.Clone());

      // Tüm düğümleri göster:

      node.Expand();

     // Sürüklenen düğümü kaldır:

      suruklenenNode.Remove();

   }

İşte, son olay yakalayıcım da burada, yani bırakma işlemi gerçekleştikten hemen sonra çalışıyor. Temel olarak yaptığı şey şu; sürükleme işlemi biter bitmez, sürüklenen TreeNode nesnesini, hedef TreeView’daki seçili Node’a ChildNode olarak eklemek. Ardından sürüklenen TreeNode’u ilk TreeView’dan kaldırmak.

 

 

 

Bu uygulamada, TreeView kontrolleri arasında sürükle-bırak işlemini incelemiş olduk. Daha sonra görüşmek üzere

Türkay ÜRKMEZ

Öneri ve istekleriniz için; turkay@turkayurkmez.com