Joseph Michael Pesch
VP Programming

C# Windows Form TreeView Drag/Drop Move and Copy Nodes, Move Nodes Up/Down and Expand on Hover

by 25. April 2014 08:13

The below code is sample of TreeView drag/drop events that supports the following:

  • Move a TreeNode by dragging and dropping with the left mouse button
  • Copy a TreeNode by dragging and dropping with the right mouse button
  • Move a TreeNode up one node by double-clicking it with the left mouse button
  • Move a TreeNode down one node by double-clicking it with the right mouse button
#region Treeview Drag/Drop Events

private void TestIt()
{
  this.MyTreeView.AllowDrop = true;
  // Add sample nodes
  TreeNode node;
  for (int x = 0; x < 5; ++x)
  {
    // Add the root node
    node = this.MyTreeView.Nodes.Add(String.Format("Node {0}", x * 4));
    for (int y = 1; y < 4; ++y)
    {
      // Add a child node to the previously added node.
      node = node.Nodes.Add(String.Format("Node{0}", x * 4 + y));
    }
  }
}
private void MyTreeView_ItemDrag(object sender, ItemDragEventArgs e)
{
  // Move the dragged node when the left mouse button is used. 
  if (e.Button == MouseButtons.Left)
  {
    DoDragDrop(e.Item, DragDropEffects.Move);
  }
  // Copy the dragged node when the right mouse button is used. 
  else if (e.Button == MouseButtons.Right)
  {
    DoDragDrop(e.Item, DragDropEffects.Copy);
  }
}

// Set the target drop effect to the effect  
// specified in the ItemDrag event handler. 
private void MyTreeView_DragEnter(object sender, DragEventArgs e)
{
  e.Effect = e.AllowedEffect;
}

// Select the node under the mouse pointer to indicate the  
// expected drop location. 

TreeNode lastDragDestination = null;
DateTime lastDragDestinationTime;
private void MyTreeView_DragOver(object sender, DragEventArgs e)
{
  // Retrieve the client coordinates of the mouse position.
  Point targetPoint = MyTreeView.PointToClient(new Point(e.X, e.Y));

  // Select the node at the mouse position.
  MyTreeView.SelectedNode = MyTreeView.GetNodeAt(targetPoint);

  TreeNode destinationNode = null;
  //get current location
  Point pt = new Point(e.X, e.Y);
  pt = MyTreeView.PointToClient(pt);
  destinationNode = MyTreeView.GetNodeAt(pt);
  if (destinationNode == null)
  {
    return;
  }

  //if we are on a new object, reset our timer
  //otherwise check to see if enough time has passed and expand the destination node
  if (destinationNode != lastDragDestination)
  {
    lastDragDestination = destinationNode;
    lastDragDestinationTime = DateTime.Now;
  }
  else
  {
    TimeSpan hoverTime = DateTime.Now.Subtract(lastDragDestinationTime);
    if (hoverTime.TotalMilliseconds > 500)
    {
      destinationNode.Expand();
    }
  }

}

private void MyTreeView_DragDrop(object sender, DragEventArgs e)
{
  // Retrieve the client coordinates of the drop location.
  Point targetPoint = MyTreeView.PointToClient(new Point(e.X, e.Y));

  // Retrieve the node at the drop location.
  TreeNode targetNode = MyTreeView.GetNodeAt(targetPoint);

  // Retrieve the node that was dragged.
  TreeNode draggedNode = (TreeNode)e.Data.GetData(typeof(TreeNode));

  // Confirm that the node at the drop location is not  
  // the dragged node or a descendant of the dragged node. 
  if (!draggedNode.Equals(targetNode) && !ContainsNode(draggedNode, targetNode))
  {
    // If it is a move operation, remove the node from its current  
    // location and add it to the node at the drop location. 
    if (e.Effect == DragDropEffects.Move)
    {
      draggedNode.Remove();
      targetNode.Nodes.Add(draggedNode);
    }

    // If it is a copy operation, clone the dragged node  
    // and add it to the node at the drop location. 
    else if (e.Effect == DragDropEffects.Copy)
    {
      targetNode.Nodes.Add((TreeNode)draggedNode.Clone());
    }

    // Expand the node at the location  
    // to show the dropped node.
    targetNode.Expand();
  }
}

// Determine whether one node is a parent  
// or ancestor of a second node. 
private bool ContainsNode(TreeNode node1, TreeNode node2)
{
  // Check the parent node of the second node. 
  if (node2.Parent == null) return false;
  if (node2.Parent.Equals(node1)) return true;

  // If the parent node is not null or equal to the first node,  
  // call the ContainsNode method recursively using the parent of  
  // the second node. 
  return ContainsNode(node1, node2.Parent);
}

private void MyTreeView_DoubleClick(object sender, EventArgs e)
{
  // Retrieve the client coordinates of the mouse position.
  Point targetPoint = new Point(((MouseEventArgs)e).X, ((MouseEventArgs)e).Y);

  // Select the node at the mouse position.
  this.MyTreeView.SelectedNode = this.MyTreeView.GetNodeAt(targetPoint);
  if (((MouseEventArgs)e).Button.Equals(MouseButtons.Right))
    Extensions.MoveNodeDown(this.MyTreeView.SelectedNode);
  else
    Extensions.MoveNodeUp(this.MyTreeView.SelectedNode);

}

#endregion

Tags:

C#