簡體   English   中英

從DataTable向樹視圖添加子節點(C#Windows窗體)

[英]Adding Child Nodes to a Treeview from DataTable (C# Windows Forms)

我在嘗試獲取Treeview來顯示子注釋時遇到了困難。

我有一個DataTable,其中填充了來自查詢的數據。

桌子是這樣的。

| ParentOT | ChildOT
  -------------------
  1        | 2
  1        | 3
  1        | 4
  4        | 5
  5        | 6

現在,我需要在TreeView中訂購此數據。

結果必須是這樣的(使用同一表)

1
|
--2
|
--3
|
--4
  |
  --5
    |
    --6

我嘗試在Windows窗體上執行此操作,我唯一能得到的就是只顯示1個孩子的樹。 像這樣

1
|
--2
|
--3
|
--4
|
--5
|
5
|
--6

我試圖這樣做:

DataTable arbolSub = mssql_cnn.ejecutarSqlSelect(q2);

            //Metodo 2: muestra las ot correctamente pero no muestra mas detalle de subOT.
            if (trvOTHs.Nodes.Count > 0)
            {
                trvOTHs.Nodes.Clear();
            }

            trvOTHs.BeginUpdate();

            if (arb.Rows.Count > 0)
            {
                string otPadre = arb.Rows[0][0].ToString();
                int nivel = 0;

                trvOTHs.Nodes.Add(arbolSub.Rows[0]["OT Padre"].ToString());

                for (int i = 0; i < arbolSub.Rows.Count; i++)
                {
                    //trvOTHs.Nodes.Add(arbolSub.Rows[0]["OT Padre"].ToString());                  
                    if (arbolSub.Rows[i]["OT Padre"].ToString() == otPadre)
                    {
                        if (trvOTHs.Nodes[nivel].Text == otPadre)
                        {
                            trvOTHs.Nodes[nivel].Nodes.Add(arbolSub.Rows[i]["OT Hija"].ToString());
                        }
                    }
                    else
                    {
                        otPadre = arbolSub.Rows[i+1]["OT Padre"].ToString();
                        TreeNode nodo = new TreeNode(otPadre.ToString());
                        trvOTHs.Nodes.Add(nodo);
                        nivel++;
                    }

                }


                trvOTHs.Nodes[0].Remove();

                trvOTHs.ExpandAll();
            }

            trvOTHs.EndUpdate();

其中trvOTHs是TreeView。

請幫忙! 謝謝

編輯 :感謝您的答復。 我終於解決了這個問題,使用了一個朋友的想法,並使用了@Mohammad abumazen建議的解決方案。

我最終遞歸地使用了兩種方法:

 private TreeView cargarOtPadres(TreeView trv, int otPadre, DataTable datos)
    {
        if (datos.Rows.Count > 0)
        { 
            foreach (DataRow dr in datos.Select("OTPadre='"+ otPadre+"'"))
            {
                TreeNode nodoPadre = new TreeNode();
                nodoPadre.Text = dr["OTPadre"].ToString();
                trv.Nodes.Add(nodoPadre);
                cargarSubOts(ref nodoPadre, int.Parse(dr["OTHija"].ToString()), datos);
            }
        }
        return trv;
    }

    private void cargarSubOts(ref TreeNode nodoPadre, int otPadre, DataTable datos)
    {
        DataRow[] otHijas = datos.Select("OTPadre='" + otPadre +"'");
        foreach (DataRow drow in otHijas)
        {
            TreeNode hija = new TreeNode();
            hija.Text = drow["OTHija"].ToString();
            nodoPadre.Nodes.Add(hija);
            cargarSubOts(ref hija, int.Parse(drow["OTHija"].ToString()), datos);
        }
    }

做到了。 如果有人需要,我把它留在這里。 再次感謝。

您代碼中的主要問題是您沒有在樹視圖中尋找要添加的子父對象,而是將它們全部添加到了主父對象中。

我對您的代碼進行了一些更改,希望它可以直接運行或在您身邊進行較小的更改:

        if (arb.Rows.Count > 0)
        {
            TreeNode MainNode = new TreeNode();

            string otPadre = arb.Rows[0][0].ToString();
            int nivel = 0;

            MainNode.Text = otPadre;
            trvOTHs.Nodes.Add(MainNode);

            for (int i = 0; i < arbolSub.Rows.Count; i++)
            {        

            TreeNode child = new TreeNode();
            child.Text = row["OT Hija"].ToString();

            if (arbolSub.Rows[i]["OT Padre"].ToString() == otPadre)
            {
                MainNode.Nodes.Add(child);  
            }
            else
            {
                FindParent(MainNode, row["OT Padre"].ToString(), child);
            }

            }

            trvOTHs.ExpandAll();
        }

這個函數找到父節點:

    private void FindParent(TreeNode ParentNode, string Parent, TreeNode ChildNode)
    {
        foreach (TreeNode node in ParentNode.Nodes)
        {
            if (node.Text.ToString() == Parent)
            {
                node.Nodes.Add(ChildNode); 
            }
            else
            {
                FindParent(node, Parent, ChildNode);
            }
        }
    }

我會做這樣的事情,您應該考慮使用DictionaryHashSet以獲得最佳性能:

//use this extension method for convenience
public static class TreeViewExtension {
  public static void LoadFromDataTable(this TreeView tv, DataTable dt){
        var parentNodes = dt.AsEnumerable()
                            .GroupBy(row => (string)row[0])
                            .ToDictionary(g=> g.Key, value=> value.Select(x=> (string)x[1]));
        Stack<KeyValuePair<TreeNode,IEnumerable<string>>> lookIn = new Stack<KeyValuePair<TreeNode,IEnumerable<string>>>();
        HashSet<string> removedKeys = new HashSet<string>();
        foreach (var node in parentNodes) {
            if (removedKeys.Contains(node.Key)) continue;
            TreeNode tNode = new TreeNode(node.Key);
            lookIn.Push(new KeyValuePair<TreeNode,IEnumerable<string>>(tNode,node.Value));
            while (lookIn.Count > 0) {
                var nodes = lookIn.Pop();                    
                foreach (var n in nodes.Value) {
                    IEnumerable<string> children;
                    TreeNode childNode = new TreeNode(n);
                    nodes.Key.Nodes.Add(childNode);
                    if (parentNodes.TryGetValue(n, out children)) {
                        lookIn.Push(new KeyValuePair<TreeNode,IEnumerable<string>>(childNode,children));
                        removedKeys.Add(n);
                    }
                }
            }
            tv.Nodes.Add(tNode);
        }
    }
}
//usage    
treeView1.LoadFromDataTable(yourDataTable);

注意 ,輸入DataTable應包含您在問題中發布的數據。 不需要其他種類的Sub-DataTable

謝謝回復。 我終於解決了這個問題,使用了一個朋友的想法,並使用了@Mohammad abumazen建議的解決方案。

我最終遞歸地使用了兩種方法:

private TreeView cargarOtPadres(TreeView trv, int otPadre, DataTable datos)
{
    if (datos.Rows.Count > 0)
    { 
        foreach (DataRow dr in datos.Select("OTPadre='"+ otPadre+"'"))
        {
            TreeNode nodoPadre = new TreeNode();
            nodoPadre.Text = dr["OTPadre"].ToString();
            trv.Nodes.Add(nodoPadre);
            cargarSubOts(ref nodoPadre, int.Parse(dr["OTHija"].ToString()), datos);
        }
    }
    return trv;
}

private void cargarSubOts(ref TreeNode nodoPadre, int otPadre, DataTable datos)
{
    DataRow[] otHijas = datos.Select("OTPadre='" + otPadre +"'");
    foreach (DataRow drow in otHijas)
    {
        TreeNode hija = new TreeNode();
        hija.Text = drow["OTHija"].ToString();
        nodoPadre.Nodes.Add(hija);
        cargarSubOts(ref hija, int.Parse(drow["OTHija"].ToString()), datos);
    }
}

做到了。 如果有人需要,我把它留在這里。 再次感謝。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM