.NET TreeView FAQ - Drag and Drop Right Click Menu

.NET TreeView Control code samples for right clicking nodes, drag and drop nodes between two TreeView controls, and nudging TreeView nodes up and down in sibling order.

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; }
    }

By Robbe Morris   Popularity  (11692 Views)
Picture
Biography - Robbe Morris
Robbe has been a Microsoft MVP in C# since 2004. He is also the co-founder of NullSkull.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