.NET TreeView FAQ - Drag and Drop Right Click Menu

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.

1.  Right Click Show Context Menu:

ContractedBlock.gif ExpandedBlockStart.gif Code
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 == nullreturn;
          
          
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:

ContractedBlock.gif ExpandedBlockStart.gif Code
     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:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
 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.

 

ContractedBlock.gif ExpandedBlockStart.gif Code
  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; } 
    }

 

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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值