Как я могу перетащить узел в treeview, но он будет находиться на уровне глубины узла ?
В этом коде я могу перетаскивать узлы и менять их местами.
Проблема заключается в том, что если я перетащу дочерний узел на любой уровень глубины, он опустит узел/ы на верхний корневой уровень 0.
Мне нужно знать, как сохранить уровень глубины узлов, чтобы, например, если я перетаскиваю узел на уровне глубины 3, то узел должен двигаться по индексам уровня 3, а не уровня 0.
Но как мне сказать ему, чтобы он перетаскивался на уровне узла ?
<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) { // background 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)); } // icon 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); } // text (due to OwnerDrawText mode, indenting of e.Bounds will be correct) TextRenderer.DrawText(e.Graphics, e.Node.Text, Font, e.Bounds, ForeColor); // indicate selection (if not by backColor): if ((e.State & TreeNodeStates.Selected) != 0) ControlPaint.DrawFocusRectangle(e.Graphics, e.Bounds); } protected override void OnItemDrag(ItemDragEventArgs e) { // Move the dragged node when the left mouse button is used. if (e.Button == MouseButtons.Left) { DoDragDrop(e.Item, DragDropEffects.Move); } // Copy the dragged node when the right mouse button is used. 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) { // Retrieve the client coordinates of the mouse position. Point targetPoint = this.PointToClient(new Point(e.X, e.Y)); // Select the node at the mouse position. this.SelectedNode = this.GetNodeAt(targetPoint); } protected override void OnDragDrop(DragEventArgs e) { // Retrieve the client coordinates of the drop location. Point targetPoint = this.PointToClient(new Point(e.X, e.Y)); // Retrieve the node at the drop location. TreeNode targetNode = this.GetNodeAt(targetPoint); // Retrieve the node that was dragged. TreeNode draggedNode = (TreeNode)e.Data.GetData(typeof(TreeNode)); //draggedNode.Level; // Confirm that the node at the drop location is not // the dragged node or a descendant of the dragged node. if (!draggedNode.Equals(targetNode))// && !ContainsNode(draggedNode, targetNode)) { // If it is a move operation, remove the node from its current // location and add it to the node at the drop location. if (e.Effect == DragDropEffects.Move) { // To check nad make that the indexs if the dragged and target nodes // Are childs to get the index of them in the place they are in the tree level // Now the indexs are belong to the root to the top of the tree. // So if a child index is 2 or 0 it will remove it and make the switch at the // Top level depth root. Instead where the childs are. 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); } // If it is a copy operation, clone the dragged node // and add it to the node at the drop location. 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), }); } } }
Часть make the drag and drop находится внутри OnDragDrop :
int draggedindex = draggedNode.Index; int targetindex = targetNode.Index; draggedNode.Remove(); targetNode.Remove(); this.Nodes.Insert(targetindex, draggedNode); this.Nodes.Insert(draggedindex, targetNode);
Но опять же он опустит перетаскиваемый узел и целевой узел до уровня 0, даже если я перетащил узел на уровень 3, так как он думает, что индексы имеют уровень 0. Я не знаю, как сказать ему, чтобы он перетащил индекс уровня, на котором находятся узлы.
Этот код в форме 1 предназначен для тестирования я сделал это чтобы увидеть все уровни глубины узлов :
<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); } } }
Итак, теперь я знаю, например, что в списке уровней индекс 0 находится на уровне 0, а индекс 1-на уровне 4, индекс 2-на уровне 0, индекс 3-на уровне 2, индекс 4-на уровне 3 и так далее.
Но я все еще не могу понять, как сделать это в OnDragDrop ?
Что я уже пробовал:
То, что я пробовал, не так уж много, так как я не могу понять, что делать.
BillWoodruff
"Итак, если я перетаскиваю узел на глубину уровня 3, например, так что узел должен двигаться по индексам уровня 3, а не уровня 0." Я не совсем понимаю, что это значит.
Вы имеете в виду, что хотите, чтобы отброшенный узел стал дочерним узлом узла, на который он отброшен ?
Или ты имеешь в виду что-то другое ?