利用這篇紀錄
[C#] TreeView for WebForm 內的資料來練習 WinForm 的 TreeView
Project 內就一個 Form 而已
控件 Layout:左邊是 TreeView,右邊是 TextBox
C# Code
namespace TreeViewOrganization
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// 預設為 false
treeView1.CheckBoxes = true;
// 預設為 true
treeView1.ShowLines = true;
DataTable dt = GetTreeData();
TreeBuild(dt);
treeView1.ExpandAll();
treeView1.AfterSelect += TreeView1_AfterSelect;
treeView1.AfterCheck += TreeView1_AfterCheck;
FocusOnRoot();
}
private void FocusOnRoot()
{
// TreeView 建置完成後,Focus 要出現在 Root 上
this.treeView1.SelectedNode = this.treeView1.Nodes[0];
}
// 把點選 TreeNode 資訊顯示在 txtNodeInfo 裡
private void TreeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
StringBuilder sb = new StringBuilder();
// 該階層索引值
sb.AppendLine($"Index:{e.Node.Index}");
// Name 必須在 TreeView 中是唯一的
sb.AppendLine($"Name:{e.Node.Name}");
// TreeNode 文字
sb.AppendLine($"Text:{e.Node.Text}");
// 備註說明,為 Object
sb.AppendLine($"Tag:{e.Node.Tag}");
// 父 TreeNode
string Parent = e.Node.Parent == null ? "Root" : e.Node.Parent.Text;
sb.AppendLine($"Parent:{Parent}");
// 子節點數量
sb.AppendLine($"Count:{e.Node.GetNodeCount(false)}");
// 完整路徑
sb.AppendLine($"FullPath:{e.Node.FullPath}");
// 該 TreeNode Level 值
sb.AppendLine($"FullPath:{e.Node.Level}");
txtNodeInfo.Text = sb.ToString();
}
// 根據點選 TreeNode CheckBox 狀態,來變成子節點
private void TreeView1_AfterCheck(object sender, TreeViewEventArgs e)
{
foreach (TreeNode ChildeNode in e.Node.Nodes)
{
ChildeNode.Checked = e.Node.Checked;
}
}
// 對應資料來源 DataTable 的欄位索引
private int IDColIndex = 0;
private int ParentIDColIndex = 1;
private int TextColIndex = 2;
private void TreeBuild(DataTable dt)
{
TreeRootExist(dt);
CreateRootNode(this.treeView1, dt);
}
private void TreeRootExist(DataTable dt)
{
EnumerableRowCollection<DataRow> result = dt
.AsEnumerable()
.Where(r => r.Field<string>(this.ParentIDColIndex) == null);
if (result.Any() == false)
throw new Exception("沒有 Root 節點資料,無法建立 TreeView");
if (result.Count() > 1)
throw new Exception("Root 節點超過 1 個,無法建立 TreeView");
}
private DataRow GetTreeRoot(DataTable dt)
{
return dt.AsEnumerable()
.Where(r => r.Field<string>(this.ParentIDColIndex) == null)
.First();
}
private IEnumerable<DataRow> GetTreeNodes(DataTable dt, TreeNode Node)
{
return dt.AsEnumerable()
.Where(r => r.Field<string>(this.ParentIDColIndex) == Node.Name)
.OrderBy(r => r.Field<string>(this.IDColIndex));
}
private void CreateRootNode(TreeView tree, DataTable dt)
{
DataRow Root = GetTreeRoot(dt);
TreeNode Node = new TreeNode();
Node.Text = Root.Field<string>(this.TextColIndex);
Node.Name = Root.Field<string>(this.IDColIndex);
tree.Nodes.Add(Node);
CreateNode(tree, dt, Node);
}
private void CreateNode(TreeView tree, DataTable dt, TreeNode Node)
{
IEnumerable<DataRow> Rows = GetTreeNodes(dt, Node);
TreeNode NewNode;
foreach (DataRow r in Rows)
{
NewNode = new TreeNode();
NewNode.Name = r.Field<string>(this.IDColIndex);
NewNode.Text = r.Field<string>(this.TextColIndex);
Node.Nodes.Add(NewNode);
CreateNode(tree, dt, NewNode);
}
}
private DataTable GetTreeData()
{
DataTable dt = new DataTable();
dt.Columns.Add("DepID", typeof(string));
dt.Columns.Add("ParentID", typeof(string));
dt.Columns.Add("DepName", typeof(string));
dt.Rows.Add("01", null, "公司");
dt.Rows.Add("02", "01", "財務");
dt.Rows.Add("03", "01", "行政");
dt.Rows.Add("04", "03", "採購");
dt.Rows.Add("05", "03", "人資");
dt.Rows.Add("06", "03", "業務");
dt.Rows.Add("07", "03", "技術服務");
dt.Rows.Add("08", "01", "開發");
dt.Rows.Add("09", "08", "企劃");
dt.Rows.Add("10", "08", "品管");
dt.Rows.Add("11", "01", "廠務");
dt.Rows.Add("12", "11", "生產技術");
dt.Rows.Add("13", "11", "製程保全");
dt.Rows.Add("14", "11", "生產管理");
dt.Rows.Add("15", "11", "廠務室 A");
dt.Rows.Add("16", "15", "倉庫 A");
dt.Rows.Add("17", "15", "板噴生產課");
dt.Rows.Add("18", "17", "端板成型組");
dt.Rows.Add("19", "17", "箱體塗裝組");
dt.Rows.Add("20", "15", "熱交生產課");
dt.Rows.Add("21", "20", "管件組");
dt.Rows.Add("22", "20", "沖片組");
dt.Rows.Add("23", "20", "回管組");
dt.Rows.Add("24", "20", "氣焊組");
dt.Rows.Add("25", "15", "裝配生產課");
dt.Rows.Add("26", "25", "裝配一組");
dt.Rows.Add("27", "25", "裝配二組");
dt.Rows.Add("28", "11", "廠務室 B");
dt.Rows.Add("29", "28", "倉庫 B");
dt.Rows.Add("30", "28", "資材課");
dt.Rows.Add("31", "28", "板金生產課");
dt.Rows.Add("32", "31", "CNC 組");
return dt;
}
}
}