C# WinForms - 在同一 TreeViewControl 中拖放
Posted
技术标签:
【中文标题】C# WinForms - 在同一 TreeViewControl 中拖放【英文标题】:C# WinForms - DragDrop within the same TreeViewControl 【发布时间】:2014-01-21 19:23:54 【问题描述】:我正在尝试在同一控件中实现树视图项的 DragDrop。
我希望能够将一个项目从一个节点移动到另一个节点。
这是我当前的代码,当我运行它时,我可以看到项目已开始拖动,但窗口图标不允许将其拖放到控件上的任何节点。
我当前的代码
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();
【讨论】:
我知道@Francesco B. 正在解决这个人的特定问题,但我想我会添加,在函数顶部插入以下行“TreeView treeView1 = (TreeView) sender;”它变成更可重复使用。 请注意,如果您已经创建了自己的 TreeNode 类,则必须在调用 e.Data.GetData 时使用该类型名称,否则 draggedNode 将变为 null。【参考方案2】:在树控件上设置AllowDrop=true
。
【讨论】:
必须修复我的回复,我确实忘记设置 AllowDrop 但它仍然无法正常工作:( - 我正在做一些调整,可能很快会更新我的帖子【参考方案3】:略微改进的版本,可防止您将节点放到自身或其任何后代上
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 处理程序进行了一些改进和添加,以配合所有其他修订。
添加支持:
支持将节点拖放到树视图背景上(底部)。节点被添加到树的底部。 合并了 mrpurple 的“不要放在子节点上”示例并对其进行了修饰,使其与原始示例一致。 还这样做了,以便在拖放节点后选中它。建议在此处也加载已删除节点的内容,否则 用户可能会对当前显示的内容与选择的节点感到困惑。注意:请务必在树视图控件上设置 AllowDrop=true,否则无法删除节点。
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);
【讨论】:
以上是关于C# WinForms - 在同一 TreeViewControl 中拖放的主要内容,如果未能解决你的问题,请参考以下文章
尝试在同一连接中运行多个命令时 C# Winforms Npgsql 3.0.5“操作已在进行中”错误
使用 PostgreSql 和 ADO.NET 在 C# WinForms 中锁定记录和表