星期二, 7月 19, 2016

[C#] TreeView for WinForm

利用這篇紀錄 [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;
        }
    }
}

沒有留言:

張貼留言