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 handle 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 TreeNavigator.
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 TreeNavigator.
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 TreeNavigator
View sample in GitHub