.NET TreeView FAQ - Drag and Drop Right Click Menu

By Robbe Morris

Working with a Windows Forms .NET TreeView control? This article contains code samples for the most common questions I've recevied. Things such as right click on nodes to show context menues, drag and drop nodes on the same TreeView or even another control, nudge nodes up and down in sibling order, and much more.

Please download the working sample.  It is derived from an old article I did
on an alternative approach concerning data binding a DataSet to a TreeView.

 Download Code

1.  Right Click Show Context Menu

    private ContextMenu tvSample1Menu = new ContextMenu();
    private  TreeView tvSample = new TreeView();
 
    private void tvSample_MouseDown(object sender,
                                     System.Windows.Forms.MouseEventArgs e)
    {

        TreeViewUtil.SetSelectedNodeByPosition(tvSample,e.X,e.Y);

        if (tvSample.SelectedNode == null) { return; }

        if (e.Button == MouseButtons.Right) { return; }

    }
 
    private void tvSample_MouseUp(object sender,
                                   System.Windows.Forms.MouseEventArgs e)
    {

      switch (e.Button)
      {
         case MouseButtons.Right:
               
         tvSample1Menu.Show(tvSample,new Point(e.X,e.Y));               
     break;

         default:
           break;
      }
    }
   

     public void SetSelectedNodeByPosition(TreeView tv,
                                           int mouseX,
                                           int mouseY)
     {
           
        TreeNode node = null;

        try
        {

          Point pt = new Point(mouseX,mouseY);
         
          tv.PointToClient(pt);
         
          node = tv.GetNodeAt(pt);

          tv.SelectedNode = node;

          if (node == null) return;
         
          if (!node.Bounds.Contains(pt)) { return; }

        }
        catch { }
        return;
      }

2.  Show Context Menu dynamically on selected node.
     This method uses the placement on screen of the
     selected node.  ContextMenus can be draw by position.
     Also, you could just as easily programmatically create
     the ContextMenu versus passing one in like this:

     public void ShowContextMenu(TreeView tv,ContextMenu menu)
     {
    
        try
        {
     
           Point pt = new Point(tv.SelectedNode.Bounds.Left,
                                tv.SelectedNode.Bounds.Bottom);

               menu.Show(tv,pt);
        }
        catch (Exception) { throw; }
      }



3.  Nudge TreeNode Sibling Order Up Or Down

     public bool NudgeDown(TreeNode node)
     {

       int newIndex = 0;
       TreeNode nodeClone = null;
      
           
       try
       {

         if (node == null) { return false; }

         newIndex = node.Index + 2;

         if (newIndex > node.Parent.Nodes.Count) { return false; }

      
         nodeClone = (TreeNode)node.Clone();
                       
         node.Parent.Nodes.Insert(newIndex, nodeClone);

         node.Parent.Nodes.Remove(node);

         nodeClone.TreeView.SelectedNode = nodeClone;

        }
        catch (Exception) { throw; }
        return true;
     }


     public bool NudgeUp(TreeNode node)
     {
       int newIndex = 0;
       TreeNode nodeClone = null;
           
       try
       {

         if (node == null) { return false; }

         if (node.Index == 0) { return false; }

         newIndex = node.Index - 1;

         nodeClone = (TreeNode)node.Clone();

         node.Parent.Nodes.Insert(newIndex, nodeClone);

         node.Parent.Nodes.Remove(node);

         nodeClone.TreeView.SelectedNode = nodeClone;
       }
       catch (Exception) { throw; }
       return true;
    }


4.  Drag And Drop On Same TreeView or Different Treeview Control.
    Download the code sample for additional information.

    Form Events
   
    private void tvSample_ItemDrag(object sender,
                                  System.Windows.Forms.ItemDragEventArgs e)
    {
      DoDragDrop(e.Item, DragDropEffects.Move);
    }

    private void tvSample_DragEnter(object sender,
                                    System.Windows.Forms.DragEventArgs e)
    {        
      this.DragEnter((TreeView)sender,e);
    }

    private void tvSample_DragOver(object sender,
                                   System.Windows.Forms.DragEventArgs e)
    {
       this.DragOver((TreeView)sender,e);
    }

    private void tvSample_DragDrop(object sender,
                                   System.Windows.Forms.DragEventArgs e)
    {
    
      bool dropOnNewControl = false;

      try
      {
      
     
      
       this.DragDrop((TreeView)sender,e,ref dropOnNewControl);

       if (dropOnNewControl)
       {
          // Perform action on old and
          // new control
       }

      }
      catch (Exception err) { Messagebox.Show(err.Message); }
      }

    
    Resuable methods

    public void DragOver(TreeView tv,System.Windows.Forms.DragEventArgs e)
    {

      try
      {

        if (!e.Data.GetDataPresent(NodeObjectName, true)) { return; }

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

        TreeNode tgtnode = tv.GetNodeAt(pt);
      
        if (tv.SelectedNode != tgtnode)
        {
       
          tv.SelectedNode = tgtnode;
         
          TreeNode drop = (TreeNode)e.Data.GetData(NodeObjectName);

          while (tgtnode != null)
          {

           if (tgtnode == drop)
           {
             e.Effect = DragDropEffects.None;
             return;
           }

           tgtnode = tgtnode.Parent;
          }
       
        }

        e.Effect = DragDropEffects.Move;
     }
     catch (Exception) { throw; }
   }

   public void DragDrop(TreeView tv,
                        System.Windows.Forms.DragEventArgs e,
                        ref bool dropOnNewControl)
   {
   
   
      try
      {

       dropOnNewControl = false;

       // Was the target control enabled to accept controls
       // being dropped on it and was it successful?

       if (!e.Data.GetDataPresent(NodeObjectName,true)) { return; }
       
       // If not working solely with TreeViews,you'll
       // to perform a .GetType() on .GetData prior to casting
       // to a specific object.

       TreeNode drop = (TreeNode)e.Data.GetData(NodeObjectName);

       TreeNode tgtnode = tv.SelectedNode;

       if (drop == drop.TreeView.Nodes[0])
       {
         // the drop node is the root of the tree.
         // You may not want to permit this.
         return;
       }

       if (drop == tgtnode)
       {
         // Jump out if dropped on self.
         return;
       }

   
       if (tgtnode.TreeView == drop.TreeView)
       {
         // If same control, act accordingly
        
       }
       else
       {
         dropOnNewControl = true;
         // This is a different control that the node
         // was dropped on.  You may now need to sync
         up the old object's underlying data.
       }

       // This removes the TreeNodes from the TreeView.

       drop.Remove();

       if (tgtnode == null)
       {
         tv.Nodes.Add(drop);
       }
       else
       {
         tgtnode.Nodes.Add(drop);
       }
       
       drop.EnsureVisible();

       tv.SelectedNode = drop;
             
      }
      catch (Exception) { throw; }
    }
Popularity  (9319 Views)
Picture
Biography - Robbe Morris
Robbe has been a Microsoft MVP in C# since 2004. He is also the co-founder of EggHeadCafe.com which provides .NET articles, book reviews, software reviews, and software download and purchase advice.  Robbe also loves to scuba dive and go deep sea fishing in the Florida Keys or off the coast of Daytona Beach. Microsoft MVP
Create New Account
Article Discussion: TreeView FAQ
Robbe Morris posted at Friday, October 20, 2006 10:44 AM
Storeing datareader value in a Array
shams khan replied to Robbe Morris at Tuesday, December 26, 2006 8:50 PM

can any body help me

my question is

i am getting the data from datareader and that values from data reader i want to store in any array

thanks & Regards   

khan

 

 

SetAsSelectedNode
Johan Pingree replied to Robbe Morris at Tuesday, December 26, 2006 8:50 PM

Mr. Morris,

How does one set a node as the selected node programmitcally in a Wins Form application on the Treeview control?  I have data that I am loading into the form. I allow the user to set a default value on a previous form. That value is a loaded node in the treeview control in the new form they open up. I have already discovered how to expand to the node in the list however I cannot get it to show the node in a "selected" mode/status/state/oriantation, thus even though I am able to show that node and it's siblings expanded in the treeview I have no way of syncranizing it with the data that is loaded. IMHO there seems to be a property that is missing from this control: like SetAsSelectedNode..

Read the code sample more closely
Robbe Morris replied to Johan Pingree at Tuesday, December 26, 2006 8:50 PM
The to set the treeView.SelectedNode object is in there.
Ok found it and thank you
Johan Pingree replied to Robbe Morris at Tuesday, December 26, 2006 8:50 PM

thanks I should have looked at your code first.

How to do these thing in a web form ?
suman das replied to Robbe Morris at Tuesday, December 26, 2006 8:50 PM

I want this to happen in asp.net web form .how to do this ...please help.

best regards

 suman

Treeview ContextMenu..
Kannabiran . replied to Robbe Morris at Tuesday, December 26, 2006 8:50 PM

Mr Morris,

    Im getting the error in TreeViewUtil The error is the name TreeViewUtil does not exixt in the current context...What i have to do..do i want to refer any namespaces?

 

Regards

Kanna

elad replied to suman das at Tuesday, December 26, 2006 8:50 PM
i also need this, please help...