|
|
Title |
Simple Drap and Drop of items in a Tree control.
|
Summary |
This is a poor demonstration of how to implement drag and drop in a tree control to move items and whole branchs arround in a tree control. It does not support moving to other controls or windows. |
Contributor |
John McTainsh
|
Published |
1-Aug-2001 |
Last updated |
1-Aug-2001 |
|
|
Introduction
Here we will show how to move and copy items on a tree control using drag and
drop. This is a very poor hack at dragging and dropping items around a tree
control. It works but has the following limitations;
Limitations
- It is possible to trick the tree by dragging the item off the tree and
dropping it somewhere else then returning it.
- The argument passed as the drag object is only a text path not the actual
node.
- When an item is dragged back onto the tree it is not tracked on the tree.
- The user can only copy and move nodes around on this tree.
Performing a Drag and Drop
Firstly we will add some items to the tree control. For this example the tree
control has been named m_tree .
/// <summary>
/// Setup the tree control items when the form is loaded.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Load(object sender, System.EventArgs e)
{
m_tree.Nodes.Add( "Root" );
m_tree.Nodes[ 0 ].Nodes.Add( "First sub node" );
m_tree.Nodes[ 0 ].Nodes.Add( "Second sub node" );
m_tree.Nodes.Add( "Second root node" );
}
The following code will perform the drag and drop operation as follows;
ItemDrag is what starts the drag. Here we decide to copy or
move depending on the state of the CTRL key.
DragEnter is called when the drag starts and sets the type of
operations that can happen with this tree.
DragOver is called when ever the mouse moves. This allows the
items in the tree to be highlighted when the mouse moves over them.
DragDrop is where it all ends and the drag action results in
a move or a copy.
// This variable holds the item currently being moved.
private TreeNode m_treeNodeDrag = null;
/// <summary>
/// Here we begin the move operation. We take the current item and determine
/// the type of drag.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void m_tree_ItemDrag(object sender, System.Windows.Forms.ItemDragEventArgs e)
{
// Record who is dragging.
m_treeNodeDrag = (TreeNode)e.Item;
// Move or if CTRL pressed Copy
DragDropEffects dropEffect = DragDropEffects.Move;
if( ( Control.ModifierKeys & Keys.Control ) != 0 )
dropEffect = DragDropEffects.Copy;
// Record who is moving to cross check with drop.
m_tree.DoDragDrop( m_treeNodeDrag.FullPath, dropEffect );
}
/// <summary>
/// This is called once at the start of the drag operation. It sets the
/// type of cursor to display.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void m_tree_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
{
e.Effect = DragDropEffects.Move | DragDropEffects.Copy;
}
/// <summary>
/// This is called when ever the mouse moves when something is being
/// dragged over the tree control.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void m_tree_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
{
Point pt = new Point( e.X, e.Y );
// Verify it is the correct data source.
if( m_treeNodeDrag.FullPath == e.Data.GetData(DataFormats.Text).ToString() )
m_tree.SelectedNode = m_tree.GetNodeAt( m_tree.PointToClient( pt ) );
else
e.Effect = DragDropEffects.None;
}
/// <summary>
/// This is called when an item is dropped onto the tree control window. Only
/// if the Effect is Copy or Move will the item be dropped causing this
/// method to activate.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void m_tree_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
{
MessageBox.Show("Drop"+e.ToString(), sender.ToString());
// Lock screen during change. (Only necessary for large moves)
Cursor.Current = Cursors.WaitCursor;
m_tree.BeginUpdate();
Point pt = new Point( e.X, e.Y );
TreeNode tnDestination = m_tree.GetNodeAt( m_tree.PointToClient( pt ) );
m_tree.SelectedNode = tnDestination;
tnDestination.Nodes.Add( (TreeNode)m_treeNodeDrag.Clone() );
tnDestination.Expand();
if( e.AllowedEffect == DragDropEffects.Move )
m_treeNodeDrag.Remove();
// End the updating stage
m_tree.EndUpdate();
Cursor.Current = Cursors.Default;
m_treeNodeDrag = null;
}
Using the private member variable m_treeNodeDrag to indicate
which node is moving is a bad thing. It should be some sort of item what is
serialised to the drag object data.
|