How to drag and drop TreeMenuItem in WinForms TreeNavigator?
The following steps guide to achieve drag and drop the TreeMenuItem in TreeNavigator
Step 1: Inherit TreeMenuItem
C#
/// <summary>
/// Advanced TreeMenuItem class
/// </summary>
public class TreeMenuItemAdv : TreeMenuItem
{
public TreeMenuItemAdv()
{
this.AllowDrag = true;
}
/// <summary>
/// Hold whether it can be dragged
/// </summary>
private bool m_AllowDrag = false;
/// <summary>
/// Gets or Sets whether to allow drag
/// </summary>
public bool AllowDrag
{
get { return m_AllowDrag; }
set { m_AllowDrag = value; }
}
}
Step 2: Invoke events to Drag and Drop
It can be achieved by handling the following events.
Event | Description |
DragEnter
| This event will be raised when user starts dragging the TreeMenuItem.
|
DragDrop
| This event will occur, when user drops the TreeMenuItem.
|
MouseDown
| This event will occur, when Mouse Button is clicked on TreeMenuItem Bounds.
|
MouseUp | This event will occur, when Mouse Button is clicked and released on TreeMenuItem Bounds.
|
MouseMove | This event will occur, when Mouse pointer is moved on TreeMenuItem Bounds. |
You can provide the below drag and drop option in TreeNavigator.
1.TreeMenuItem will drag and drop between two TreeNavigators.
C#
//TreeMenuItem drag/drop option between two TreeNavigator
this.DestinationTreeNavigator.ParentPanel.DragEnter += Outside_DragEnter;
this.DestinationTreeNavigator.ParentPanel.DragDrop += Outside_DragDrop;
/// <summary>
/// Occurs when Items Dropped
/// </summary>
private void Outside_DragDrop(object sender, DragEventArgs e)
{
IntPtr hWnd = WindowFromPoint(Control.MousePosition);
if (hWnd != IntPtr.Zero)
{
TreeMenuItemAdv ctrlUnderMouse = (TreeMenuItemAdv)Control.FromHandle(hWnd);
if (ctrlUnderMouse != null)
{
TreeMenuItemAdv menuDrop = e.Data.GetData(e.Data.GetFormats()[0]) as TreeMenuItemAdv;
if (menuDrop != null)
{
this.SourceTreeNavigator.Items.Remove(menuDrop);
if (menuDrop.ParentItem != null)
{
for (int i = 0; i < menuDrop.ParentItem.ChildCollection.Count; i++)
{
if (menuDrop.ParentItem.ChildCollection[i].ChildTreeMenuItemAdv == menuDrop)
{
menuDrop.ParentItem.ChildCollection.Remove(menuDrop.ParentItem.ChildCollection[i]);
break;
}
}
for (int i = 0; i < menuDrop.ParentItem.ChildCollection.Count; i++)
{
for (int j = 0; j < menuDrop.ChildCollection.Count; j++)
{
if (menuDrop.ParentItem.ChildCollection[i].ChildTreeMenuItemAdv == menuDrop.ChildCollection[j].ChildTreeMenuItemAdv)
{
menuDrop.ParentItem.ChildCollection.Remove(menuDrop.ParentItem.ChildCollection[i]);
i = 0;
break;
}
}
}
}
menuDrop.ParentItem = null;
this.SourceTreeNavigator.UpdateVisibleItemBounds();
menuDrop.ParentControl = this.DestinationTreeNavigator;
this.DestinationTreeNavigator.Items.Insert((this.DestinationTreeNavigator.Items.IndexOf(ctrlUnderMouse)), menuDrop);
this.DestinationTreeNavigator.UpdateVisibleItemBounds();
foreach (TreeMenuItemAdvCollection item in menuDrop.ChildCollection)
{
this.SourceTreeNavigator.Items.Remove(item.ChildTreeMenuItemAdv);
item.ParentTreeMenuItemAdv = null;
}
this.SourceTreeNavigator.UpdateVisibleItemBounds();
int index = (this.DestinationTreeNavigator.Items.IndexOf(menuDrop) + 1);
for (int i = 0; i < menuDrop.ChildCollection.Count; i++)
{
if (i == 0)
{
this.DestinationTreeNavigator.Items.Insert(index, menuDrop.ChildCollection[i].ChildTreeMenuItemAdv);
}
else
{
index += 1;
this.DestinationTreeNavigator.Items.Insert(index, menuDrop.ChildCollection[i].ChildTreeMenuItemAdv);
}
menuDrop.ChildCollection[i].ChildTreeMenuItemAdv.ParentControl = this.DestinationTreeNavigator;
}
this.DestinationTreeNavigator.UpdateVisibleItemBounds();
}
}
}
}
/// <summary>
/// Occurs when Items are dragged
/// </summary>
private void Outside_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
2. TreeMenuItem will drag and drop within the TreeNavigators.
C#
//TreeMenuItem drag/drop option inside the TreeNavigator
this.SourceTreeNavigator.ParentPanel.DragEnter += ControlInside_DragEnter;
this.SourceTreeNavigator.ParentPanel.DragDrop += ControlInside_DragDrop;
/// <summary>
/// Occurs when dropped inside the control
/// </summary>
private void ControlInside_DragDrop(object sender, DragEventArgs e)
{
IntPtr hWnd = WindowFromPoint(Control.MousePosition);
if (hWnd != IntPtr.Zero)
{
TreeMenuItemAdv ctrlUnderMouse = (TreeMenuItemAdv)Control.FromHandle(hWnd);
if (ctrlUnderMouse != null)
{
TreeMenuItemAdv menuDrop = e.Data.GetData(e.Data.GetFormats()[0]) as TreeMenuItemAdv;
if (menuDrop != null)
{
this.SourceTreeNavigator.Items.Remove(menuDrop);
if (menuDrop.ParentItem != null)
{
for (int i = 0; i < menuDrop.ParentItem.ChildCollection.Count; i++)
{
if (menuDrop.ParentItem.ChildCollection[i].ChildTreeMenuItemAdv == menuDrop)
{
menuDrop.ParentItem.ChildCollection.Remove(menuDrop.ParentItem.ChildCollection[i]);
break;
}
}
for (int i = 0; i < menuDrop.ParentItem.ChildCollection.Count; i++)
{
for (int j = 0; j < menuDrop.ChildCollection.Count; j++)
{
if (menuDrop.ParentItem.ChildCollection[i].ChildTreeMenuItemAdv == menuDrop.ChildCollection[j].ChildTreeMenuItemAdv)
{
menuDrop.ParentItem.ChildCollection.Remove(menuDrop.ParentItem.ChildCollection[i]);
i = 0;
break;
}
}
}
}
menuDrop.ParentItem = null;
this.SourceTreeNavigator.UpdateVisibleItemBounds();
menuDrop.ParentControl = this.SourceTreeNavigator;
this.SourceTreeNavigator.Items.Insert((this.SourceTreeNavigator.Items.IndexOf(ctrlUnderMouse)), menuDrop);
this.SourceTreeNavigator.UpdateVisibleItemBounds();
foreach (TreeMenuItemAdvCollection item in menuDrop.ChildCollection)
{
this.SourceTreeNavigator.Items.Remove(item.ChildTreeMenuItemAdv);
item.ParentTreeMenuItemAdv = null;
}
this.SourceTreeNavigator.UpdateVisibleItemBounds();
int index = (this.SourceTreeNavigator.Items.IndexOf(menuDrop) + 1);
for (int i = 0; i < menuDrop.ChildCollection.Count; i++)
{
if (i == 0)
{
this.SourceTreeNavigator.Items.Insert(index, menuDrop.ChildCollection[i].ChildTreeMenuItemAdv);
}
else
{
index += 1;
this.SourceTreeNavigator.Items.Insert(index, menuDrop.ChildCollection[i].ChildTreeMenuItemAdv);
}
menuDrop.ChildCollection[i].ChildTreeMenuItemAdv.ParentControl = this.SourceTreeNavigator;
}
this.SourceTreeNavigator.UpdateVisibleItemBounds();
}
}
}
}
/// <summary>
/// Occurs when Dragged inside the control
/// </summary>
private void ControlInside_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
You can handle the TreeMenuItem actions(clicked, drag effect, expand and collapse) using OnMouseDown, OnMouseMove and OnMouseUp override method in TreeMenuItemAdv class.
C#
protected override void OnMouseDown(MouseEventArgs e)
{
this.Focus();
base.OnMouseDown(e);
mousedownX = e.X;
mousedowny = e.Y;
this.isDragging = false;
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (!isDragging)
{
// This is a check to see if the mouse is moving while pressed.
// Without this, the DragDrop is fired directly when the control is clicked, now you have to drag a few pixels first.
if (e.Button == MouseButtons.Left && dragRadius > 0 && this.AllowDrag)
{
int num1 = mousedownX - e.X;
int num2 = mousedowny - e.Y;
if (((num1 * num1) + (num2 * num2)) > dragRadius)
{
DoDragDrop(this, DragDropEffects.All);
isDragging = true;
return;
}
}
base.OnMouseMove(e);
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
isDragging = false;
if (!this.Collapsed && this.ParentControl != null)
{
for (int i = 0; i < this.ChildCollection.Count; i++)
{
TreeMenuItemAdv item = this.ChildCollection[i].ChildTreeMenuItemAdv as TreeMenuItemAdv;
if (item != null && item.ParentItem == this)
{
item.Visible = false;
if (this.ParentControl != null)
this.ParentControl.SerializeScrollPosition();
this.Collapsed = true;
item.Invalidate();
}
}
}
else if (this.Collapsed && this.ParentControl != null)
{
for (int i = 0; i < this.ChildCollection.Count; i++)
{
TreeMenuItemAdv item = this.ChildCollection[i].ChildTreeMenuItemAdv as TreeMenuItemAdv;
if (item != null && item.ParentItem == this)
{
item.Visible = true;
if (this.ParentControl != null)
this.ParentControl.SerializeScrollPosition();
this.Collapsed = false;
item.Invalidate();
}
}
}
if (this.ParentControl != null)
{
this.ParentControl.UpdateVisibleItemBounds();
this.ParentControl.ApplySavedScrollPosition();
}
base.OnMouseUp(e);
}
Screenshot:

Figure i) Drag and drop within the TreeNavigator

Figure ii) Drag and drop between two TreeNavigators
View sample in GitHub