2013-10-21 51 views
-1

我很難嘗試讓Treeview顯示子註釋。從DataTable向TreeView添加子節點(C#Windows窗體)

我有一個DataTable充滿了來自查詢的數據。

表是這樣的。

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

現在,我需要的是在TreeView中訂購這些數據。

的結果必然是這樣的(使用相同的表)

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

我想這在Windows Forms和我能得到的唯一的事情就是樹只顯示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); 
     } 
    } 

這做到了。我留在這裏以防萬一需要它。再次感謝。

回答

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

我會做一些像這樣,您應該考慮使用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應包含您在問題中發佈的數據。 不需要其他種類的子數據表

0

感謝您的回覆。我終於用這個方法解決了這個問題,用一個朋友給出的想法,並使用@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); 
    } 
} 

這做到了。我留在這裏以防萬一需要它。再次感謝。