【问题标题】:Adding Child Nodes to a Treeview from DataTable (C# Windows Forms)从 DataTable 将子节点添加到 Treeview(C# Windows 窗体)
【发布时间】:2013-10-21 19:24:07
【问题描述】:

我很难让 Treeview 显示子笔记。

我有一个数据表,其中填充了来自查询的数据。

桌子是这样的。

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

现在,我需要在 TreeView 中对这些数据进行排序。

结果必须是这样的(使用同一张表)

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

我在 Windows 窗体上尝试过这个,我唯一能得到的就是树只显示一组孩子。像这样

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);
        }
    }

这样做了。我把它留在这里以防万一有人需要它。再次感谢。

【问题讨论】:

    标签: c# winforms treeview nodes


    【解决方案1】:

    您的代码中的主要问题是您不是在树视图中寻找子父级以将其添加到 下,而是将它们全部添加到主父级下。

    我对您的代码进行了一些更改,希望它可以直接工作或在您身边进行细微的更改:

            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);
                }
            }
        }
    

    【讨论】:

      【解决方案2】:

      我会这样做,您应该考虑使用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 应包含您在问题中发布的数据。 不需要其他类型的子数据表

      【讨论】:

        【解决方案3】:

        感谢您的回复。我终于解决了这个问题,使用了一个朋友给出的想法,并使用了@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);
            }
        }
        

        这样做了。我把它留在这里以防万一有人需要它。再次感谢。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-07-16
          • 2011-09-11
          • 2013-04-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-10-21
          相关资源
          最近更新 更多