TreeView 是 Windows Forms 中呈現階層式資料的核心控制項,由 TreeView 容器與 TreeNode 節點物件組成。本文系統整理節點新增 (子/兄)、刪除、展開摺疊等核心操作,並提供完整可執行範例程式碼。
TreeView:容器控制項,管理根節點集合 Nodes、選取節點 SelectedNode、影像清單 ImageList 等。TreeNode:節點物件,擁有 Nodes (子節點集合)、Parent (父節點)、Text/Tag、ImageIndex、Expand()/Collapse() 等成員。
if (treeView1.SelectedNode == null)
{
MessageBox.Show("請先選取節點");
return;
}
TreeNode child = new TreeNode("新子節點文字");
treeView1.SelectedNode.Nodes.Add(child); // 加入至 SelectedNode 的子節點集合
treeView1.SelectedNode = child; // 選取新節點
treeView1.ExpandAll(); // 展開顯示
if (treeView1.SelectedNode == null) return;
TreeNode sibling = new TreeNode("新兄弟節點文字");
// 關鍵差異:透過 Parent.Nodes 加入,而非 SelectedNode.Nodes
treeView1.SelectedNode.Parent?.Nodes.Add(sibling);
treeView1.ExpandAll();
注意:若選取的是根節點 (無 Parent),Parent 為 null,需加入判斷或改用 treeView1.Nodes.Add(...)。
if (treeView1.SelectedNode == null) return;
// 若有子節點需先清除,或遞迴刪除
if (treeView1.SelectedNode.Nodes.Count > 0)
{
MessageBox.Show("請先刪除所有子節點");
return;
}
treeView1.SelectedNode.Remove(); // 從父節點集合移除
| 操作 | 程式碼 | 說明 |
|---|---|---|
| 展開所有節點 | treeView1.Nodes[0]?.ExpandAll(); | 從根節點遞迴展開 |
| 摺疊所有節點 | treeView1.Nodes[0]?.Collapse(); | 僅摺疊根節點,子節點隨之隱藏 |
| 展開特定節點 | treeView1.SelectedNode?.Expand(); | 僅展開該節點下一層 |
| 摺疊特定節點 | treeView1.SelectedNode?.Collapse(); | 摺疊該節點 |
| 切換展開狀態 | treeView1.SelectedNode?.Toggle(); | 展開↔摺疊切換 |
using System;
using System.Drawing;
using System.Windows.Forms;
public class TreeViewDemoForm : Form
{
private TreeView treeView1;
private TextBox txtNodeName;
private ContextMenuStrip ctxMenu;
private ToolStripMenuItem miAddChild, miAddSibling, miDelete;
private Button btnExpandAll, btnCollapseAll, btnExpandOne;
public TreeViewDemoForm()
{
InitializeComponent();
// 初始根節點
treeView1.Nodes.Add("根節點");
treeView1.Nodes[0].Expand();
}
private void InitializeComponent()
{
// 控制項初始化與配置 (略)
// 重點事件繫結:
miAddChild.Click += (s, e) => AddChildNode();
miAddSibling.Click += (s, e) => AddSiblingNode();
miDelete.Click += (s, e) => DeleteNode();
treeView1.MouseDown += (s, e) =>
{ if (e.Button == MouseButtons.Right) ctxMenu.Show(treeView1, e.Location); };
btnExpandAll.Click += (s, e) => treeView1.Nodes[0]?.ExpandAll();
btnCollapseAll.Click += (s, e) => treeView1.Nodes[0]?.Collapse();
btnExpandOne.Click += (s, e) => treeView1.SelectedNode?.Expand();
}
private void AddChildNode()
{
if (treeView1.SelectedNode == null || string.IsNullOrWhiteSpace(txtNodeName.Text)) return;
var node = new TreeNode(txtNodeName.Text);
treeView1.SelectedNode.Nodes.Add(node);
treeView1.SelectedNode = node;
treeView1.ExpandAll();
}
private void AddSiblingNode()
{
if (treeView1.SelectedNode == null || string.IsNullOrWhiteSpace(txtNodeName.Text)) return;
var parent = treeView1.SelectedNode.Parent ?? treeView1; // 根節點無 Parent 時加至 TreeView.Nodes
var node = new TreeNode(txtNodeName.Text);
if (parent is TreeView tv) tv.Nodes.Add(node);
else ((TreeNode)parent).Nodes.Add(node);
treeView1.ExpandAll();
}
private void DeleteNode()
{
if (treeView1.SelectedNode == null) return;
if (treeView1.SelectedNode.Nodes.Count > 0)
{
MessageBox.Show("請先刪除子節點");
return;
}
treeView1.SelectedNode.Remove();
}
}
node.Tag = entityId 或完整物件,避免以 Text 查找。BeforeExpand 事件動態載入子節點。AllowDrop=true,處理 ItemDrag, DragEnter, DragDrop 實作節點移動。FindNodeByText 或 LINQ treeView1.Nodes.Cast<TreeNode>().SelectMany(n => n.Nodes.Cast<TreeNode>())。ObjectListView (第三方) 或自訂繼承 TreeView 實作 IBindingList (參考文章 12424)。| 問題 | 原因 | 解決 |
|---|---|---|
| 新增兄弟節點失效 | 根節點無 Parent | 判斷 Parent 是否為 null,改加至 TreeView.Nodes |
| 刪除報錯 | 節點有子節點 | 遞迴刪除或先清空 Nodes |
| 展開/摺疊無效 | 未選取節點或節點無子項 | 檢查 SelectedNode 及 Nodes.Count |
| 效能差 | 一次載入萬筆節點 | 分頁載入、虛擬模式、BeginUpdate/EndUpdate |