С# WinForms - DragDrop внутри одного TreeViewControl
Я пытаюсь реализовать DragDrop элемента treeview внутри одного элемента управления.
Я хочу иметь возможность перемещать элемент из 1 node в другой.
Вот мой текущий код. Когда я запустил это, я вижу, что элемент начал перетаскивание, но значок Windows не позволяет его удалять на любые узлы в элементе управления.
Мой текущий код
private void treeView1_ItemDrag(object sender, ItemDragEventArgs e)
{
DoDragDrop(e.Item, DragDropEffects.Move);
}
private void treeView1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
private void treeView1_DragDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(TreeNode)))
{
TreeNode sourceNode = e.Data.GetData(typeof(TreeView)) as TreeNode;
var item = new TreeNode(sourceNode.Text);
System.Drawing.Point pt = ((TreeView)sender).PointToClient(new System.Drawing.Point(e.X, e.Y));
TreeNode DestinationNode = ((TreeView)sender).GetNodeAt(pt);
DestinationNode.Nodes.Add(item);
DestinationNode.Expand();
}
}
Ответы
Ответ 1
Просто измените функцию treeView1_DragDrop
на:
private void treeView1_DragDrop(object sender, DragEventArgs e)
{
// Retrieve the client coordinates of the drop location.
Point targetPoint = treeView1.PointToClient(new Point(e.X, e.Y));
// Retrieve the node at the drop location.
TreeNode targetNode = treeView1.GetNodeAt(targetPoint);
// Retrieve the node that was dragged.
TreeNode draggedNode = (TreeNode)e.Data.GetData(typeof(TreeNode));
// Confirm that the node at the drop location is not
// the dragged node and that target node isn't null
// (for example if you drag outside the control)
if (!draggedNode.Equals(targetNode) && targetNode != null)
{
// Remove the node from its current
// location and add it to the node at the drop location.
draggedNode.Remove();
targetNode.Nodes.Add(draggedNode);
// Expand the node at the location
// to show the dropped node.
targetNode.Expand();
}
}
Ответ 2
Установите AllowDrop=true
в дереве управления.
Ответ 3
немного улучшенная версия, которая мешает вам сбросить node на себя или на любого из его потомков
private void treeView1_DragDrop(object sender, DragEventArgs e)
{
TreeNode draggedNode = (MatfloNode)drgevent.Data.GetData(typeof(TreeNode));
Point pt = this.PointToClient(new System.Drawing.Point(drgevent.X, drgevent.Y));
TreeNode targetNode = this.GetNodeAt(pt);
TreeNode parentNode = targetNode;
if (draggedNode != null &&
targetNode != null )
{
bool canDrop = true;
while (canDrop && (parentNode != null))
{
canDrop = !Object.ReferenceEquals(draggedNode, parentNode);
parentNode = parentNode.Parent;
}
if (canDrop)
{
draggedNode.Remove();
targetNode.Nodes.Add(draggedNode);
targetNode.Expand();
}
}
}
Ответ 4
Еще несколько улучшений и дополнений к обработчику DragDrop, чтобы выполнить все другие изменения.
Добавлена поддержка:
- Поддерживает удаление узлов на фоне дерева (внизу). Узлы добавляются в нижней части дерева.
- Включить пример "не качать на дочерний node" mrpurple и ухаживать за ним, чтобы он был встроен в исходный пример.
- Также сделал так, что после того, как он упал, выбирается перетаскиваемый node. Рекомендуем загружать содержимое для отброшенного node здесь, иначе в противном случае
пользователь может запутаться в том, что отображается в настоящее время, и что выбрано node.
Примечание. Убедитесь, что AllowDrop = true в элементе управления treeview, иначе вы не сможете удалить узлы.
private void treeView1_ItemDrag(object sender, ItemDragEventArgs e)
{
DoDragDrop(e.Item, DragDropEffects.Move);
}
private void treeView1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
private void treeView1_DragDrop(object sender, DragEventArgs e)
{
// Retrieve the client coordinates of the drop location.
Point targetPoint = treeView1.PointToClient(new Point(e.X, e.Y));
// Retrieve the node at the drop location.
TreeNode targetNode = treeView1.GetNodeAt(targetPoint);
// Retrieve the node that was dragged.
TreeNode draggedNode = e.Data.GetData(typeof(TreeNode));
// Sanity check
if (draggedNode == null)
{
return;
}
// Did the user drop on a valid target node?
if (targetNode == null)
{
// The user dropped the node on the treeview control instead
// of another node so lets place the node at the bottom of the tree.
draggedNode.Remove();
treeView1.Nodes.Add(draggedNode);
draggedNode.Expand();
}
else
{
TreeNode parentNode = targetNode;
// Confirm that the node at the drop location is not
// the dragged node and that target node isn't null
// (for example if you drag outside the control)
if (!draggedNode.Equals(targetNode) && targetNode != null)
{
bool canDrop = true;
// Crawl our way up from the node we dropped on to find out if
// if the target node is our parent.
while (canDrop && (parentNode != null))
{
canDrop = !Object.ReferenceEquals(draggedNode, parentNode);
parentNode = parentNode.Parent;
}
// Is this a valid drop location?
if (canDrop)
{
// Yes. Move the node, expand it, and select it.
draggedNode.Remove();
targetNode.Nodes.Add(draggedNode);
targetNode.Expand();
}
}
}
// Optional: Select the dropped node and navigate (however you do it)
treeView1.SelectedNode = draggedNode;
// NavigateToContent(draggedNode.Tag);
}