In this code I can drag and drop nodes and change the nodes places.
The problem is that if I drag a child node at any depth level it will drop the node/s at the top root level 0.
I need some how to keep the nodes depth level so if I'm dragging a node at depth level 3 for example so the node should move at the indexs of level 3 and not level 0.
But how do I tell it to drag and drop at the node level ?
<pre>using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
public class AdvancedTreeView : TreeView
{
private Bitmap openedIcon, closedIcon;
private List<TreeNode> rootNodes = new List<TreeNode>();
public AdvancedTreeView()
{
DrawMode = TreeViewDrawMode.OwnerDrawText;
ShowLines = false;
AlternateBackColor = BackColor;
ArrowColor = SystemColors.WindowText;
this.AllowDrop = true;
}
public Color AlternateBackColor { get; set; }
public Color ArrowColor { get; set; }
protected override void OnDrawNode(DrawTreeNodeEventArgs e)
{
Color backColor = (GetTopNodeIndex(e.Node) & 1) == 0 ? BackColor : AlternateBackColor;
using (Brush b = new SolidBrush(backColor))
{
e.Graphics.FillRectangle(b, new Rectangle(0, e.Bounds.Top, ClientSize.Width, e.Bounds.Height));
}
if (e.Node.Nodes.Count > 0)
{
Image icon = GetIcon(e.Node.IsExpanded);
e.Graphics.DrawImage(icon, e.Bounds.Left - icon.Width - 3, e.Bounds.Top);
}
TextRenderer.DrawText(e.Graphics, e.Node.Text, Font, e.Bounds, ForeColor);
if ((e.State & TreeNodeStates.Selected) != 0)
ControlPaint.DrawFocusRectangle(e.Graphics, e.Bounds);
}
protected override void OnItemDrag(ItemDragEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
DoDragDrop(e.Item, DragDropEffects.Move);
}
else if (e.Button == MouseButtons.Right)
{
DoDragDrop(e.Item, DragDropEffects.Copy);
}
}
protected override void OnDragEnter(DragEventArgs e)
{
e.Effect = e.AllowedEffect;
}
protected override void OnDragOver(DragEventArgs e)
{
Point targetPoint = this.PointToClient(new Point(e.X, e.Y));
this.SelectedNode = this.GetNodeAt(targetPoint);
}
protected override void OnDragDrop(DragEventArgs e)
{
Point targetPoint = this.PointToClient(new Point(e.X, e.Y));
TreeNode targetNode = this.GetNodeAt(targetPoint);
TreeNode draggedNode = (TreeNode)e.Data.GetData(typeof(TreeNode));
if (!draggedNode.Equals(targetNode))
{
if (e.Effect == DragDropEffects.Move)
{
int draggedLevel = draggedNode.Level;
int targetLevel = targetNode.Level;
int draggedindex = draggedNode.Index;
int targetindex = targetNode.Index;
draggedNode.Remove();
targetNode.Remove();
this.Nodes.Insert(targetindex, draggedNode);
this.Nodes.Insert(draggedindex, targetNode);
}
else if (e.Effect == DragDropEffects.Copy)
{
targetNode.Nodes.Add((TreeNode)draggedNode.Clone());
}
}
}
private int GetTopNodeIndex(TreeNode node)
{
while (node.Parent != null)
node = node.Parent;
return Nodes.IndexOf(node);
}
private Image GetIcon(bool nodeIsExpanded)
{
if (openedIcon == null)
InitIcons();
return nodeIsExpanded ? openedIcon : closedIcon;
}
private void InitIcons()
{
openedIcon = new Bitmap(16, 16);
closedIcon = new Bitmap(16, 16);
using (Brush b = new SolidBrush(ArrowColor))
{
using (Graphics g = Graphics.FromImage(openedIcon))
g.FillPolygon(b, new[] { new Point(0, 0), new Point(15, 0), new Point(8, 15), });
using (Graphics g = Graphics.FromImage(closedIcon))
g.FillPolygon(b, new[] { new Point(0, 0), new Point(15, 8), new Point(0, 15), });
}
}
}
The part the make the drag and drop is inside OnDragDrop :
int draggedindex = draggedNode.Index;
int targetindex = targetNode.Index;
draggedNode.Remove();
targetNode.Remove();
this.Nodes.Insert(targetindex, draggedNode);
this.Nodes.Insert(draggedindex, targetNode);
But again it will drop the dragged node and the target node to the level 0 even if I dragged a node at level 3 since it's thinking the indexes are of level 0. I don't know how to tell it to drag in the index of the level the nodes is.
This code in form1 is for testing I did it to see all the nodes depth levels :
<pre>using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Treeview_Test
{
public partial class Form1 : Form
{
List<int> levels = new List<int>();
public Form1()
{
InitializeComponent();
foreach (TreeNode node in advancedTreeView1.Nodes)
{
ListNodes(node);
}
}
void ListNodes(TreeNode node)
{
foreach (TreeNode subnode in node.Nodes)
{
ListNodes(subnode);
}
levels.Add(node.Level);
}
}
}
So now I know for example that in the List levels index 0 is at level 0 and index 1 at level 4 index 2 at level 0 index 3 at level 2 index 4 at level 3 and so on.
But I still can't figure out how to make it in the OnDragDrop ?
What I have tried:
What have I tried is not much since I can't figure out what to do.