Articles in this section
Category / Section

How to drag and drop TreeMenuItem in WinForms TreeNavigator?

4 mins read

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:

Drag and drop within the TreeNavigator

Figure i) Drag and drop within the TreeNavigator 

Drag and drop between two TreeNavigator

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

Did you find this information helpful?
Yes
No
Help us improve this page
Please provide feedback or comments
Comments (0)
Please  to leave a comment
Access denied
Access denied