實作 TreeView 節點拖放需設定 AllowDrop = true 並處理四大事件:
ItemDrag:啟動拖放作業(DoDragDrop)DragEnter:設定允許的放置效果DragOver:即時反饋目標節點(高亮選中)DragDrop:完成移動/複製邏輯
public class Form4 : Form {
private TreeView treeView1;
public Form4() {
treeView1 = new TreeView();
treeView1.AllowDrop = true;
treeView1.Dock = DockStyle.Fill;
// 建立測試節點
for (int x = 0; x < 3; x++) {
TreeNode root = treeView1.Nodes.Add($"Node{x * 4}");
for (int y = 1; y < 4; y++) root.Nodes.Add($"Node{x * 4 + y}");
}
// 事件繫結
treeView1.ItemDrag += TreeView1_ItemDrag;
treeView1.DragEnter += TreeView1_DragEnter;
treeView1.DragOver += TreeView1_DragOver;
treeView1.DragDrop += TreeView1_DragDrop;
this.ClientSize = new Size(292, 273);
this.Controls.Add(treeView1);
}
// 1. 啟動拖放:左鍵=移動,右鍵=複製
private void TreeView1_ItemDrag(object sender, ItemDragEventArgs e) {
if (e.Button == MouseButtons.Left)
DoDragDrop(e.Item, DragDropEffects.Move);
else if (e.Button == MouseButtons.Right)
DoDragDrop(e.Item, DragDropEffects.Copy);
}
// 2. 進入控制項:接受來源允許的效果
private void TreeView1_DragEnter(object sender, DragEventArgs e) {
e.Effect = e.AllowedEffect;
}
// 3. 拖曳中:高亮目標節點
private void TreeView1_DragOver(object sender, DragEventArgs e) {
Point pt = treeView1.PointToClient(new Point(e.X, e.Y));
treeView1.SelectedNode = treeView1.GetNodeAt(pt);
}
// 4. 放置:執行移動/複製,防止父子循環
private void TreeView1_DragDrop(object sender, DragEventArgs e) {
Point pt = treeView1.PointToClient(new Point(e.X, e.Y));
TreeNode target = treeView1.GetNodeAt(pt);
TreeNode dragged = (TreeNode)e.Data.GetData(typeof(TreeNode));
if (dragged == null || target == null) return;
if (dragged.Equals(target) || ContainsNode(dragged, target)) return; // 避免移至自己或子孫
if (e.Effect == DragDropEffects.Move) {
dragged.Remove();
target.Nodes.Add(dragged);
} else if (e.Effect == DragDropEffects.Copy) {
target.Nodes.Add((TreeNode)dragged.Clone());
}
target.Expand();
}
// 遞迴檢查 node1 是否為 node2 的祖先
private bool ContainsNode(TreeNode node1, TreeNode node2) {
if (node2.Parent == null) return false;
if (node2.Parent.Equals(node1)) return true;
return ContainsNode(node1, node2.Parent);
}
}
DragLeave 清除高亮選取。