2013-09-27 85 views
4

我需要創建一個從數據庫表中取得的菜單結構,該表使用ID和ParentID以及用於確定節點順序的Rank。向.NET TreeView遞歸添加節點

Root(ID 1, ParentID 0, Rank 1) 
    - Node(ID 2, ParentID 1, Rank 1) 
    - Node(ID 3, ParentID 2, Rank 1) 
     - Node(ID 4, ParentID 3, Rank 1) 
     - Node(ID 5, ParentID 3, Rank 2) 
    - Node(ID 6, ParentID 2, Rank 2) 
    - Node(ID 7, ParentID 2, Rank 3) 
    - Node(ID 8, ParentID 1, Rank 2) 
    - Node(ID 9, ParentID 8, Rank 1) 
    - Node(ID 10, ParentID 8, Rank 2) 

我試圖創建一個函數來遍歷SQL數據並創建此樹結構,但我不確定如何處理添加的深度。我可以通過簡單地檢查它們是否具有ParentID來添加第一層節點,我可以在else條件中添加第二層節點,但是我不確定如何添加以下層次的層次結構。

通過數據庫遍歷:節點

using (var command = new SqlCommand(_Query, _Connection)) 
{ 
    _Connection.Open();     
    var _Reader = command.ExecuteReader(); 
    while (_Reader.Read()) 
    { 
     CreateNode((int)_Reader["MenuID"], (int)_Reader["ParentID"], (int)_Reader["Rank"], _Reader["English"].ToString());      
    } 
    _Connection.Close(); 
} 

創作:

private void CreateNode(int id, int parentID, int rank, string text) 
{    
    if(parentID == -1) 
    { 
     TreeNode _Node = new TreeNode(text, id.ToString()); 
     Root.Nodes.Add(_Node); 
    } 

    if (parentID != -1) 
    { 
     foreach (TreeNode _Node in Root.Nodes) 
     {      
      if (_Node.Value == parentID.ToString()) 
      { 
       _Node.ChildNodes.Add(new TreeNode(text, id.ToString()) { ShowCheckBox = true }); 
      } 
     } 
    } 
} 

目前,這不是由排名挑選節點

我d期望輸出的HTML是si milar以下幾點:

<ul id="1"> 
    <li>A</li> 
    <li> 
     <ul id="2"> 
      <li>B</li> 
      <li> 
       <ul id="3"> 
        <li>C</li> 
        <li> 
         <ul id="4"> 
          <li>D</li> 
         </ul> 
        </li> 
        <li> 
         <ul id="5"> 
          <li>E</li> 
         </ul> 
        </li> 
       </ul>     
      </li> 
      <li> 
       <ul id="6"> 
        <li>F</li> 
       </ul> 
      </li> 
      <li> 
       <ul id="7"> 
        <li>G</li> 
       </ul> 
      </li>    
     </ul> 
    </li>   
    <li> 
     <ul id="8"> 
      <li>H</li> 
      <ul> 
       <li> 
        <ul id="9"> 
         <li>I</li> 
        </ul> 
       </li> 
       <li> 
        <ul id="10"> 
         <li>J</li> 
        </ul> 
       </li>     
      </ul> 
     </ul> 
    </li> 
</ul> 

http://jsfiddle.net/RjE7H/

+0

更新我的答案與一些示例代碼,讓我知道如果你需要進一步的解釋 – MichaC

回答

1

使用字典,這樣你不必痛苦地掃描你的樹的t他父:

Dictionary<int, TreeNode> ParentCache = new Dictionary<int, TreeNode>(); 
private void CreateNode(int id, int parentID, int rank, string text) 
{ 
    TreeNodeCollection parentNode = root.Nodes; 
    if(parentID != 0) 
    { 
     TreeNode foundParentNode; 
     if (!ParentCache.TryGetValue(parentID, out foundParentNode) 
      throw new Exception("Given parentID has not been added to the tree yet - " + parentID.ToString()); 
     parentNode = foundParentNode.ChildNodes; 
    } 

    TreeNode newNode = new TreeNode(text, id.ToString()); 
    parentNode.Add(newNode); 
    ParentCache.Add(id, newNode); 
} 

如果你指定的順序接收數據,然後輸出應該是含蓄的排名順序。鑑於我們總是追加到TreeNodeCollections的末尾。

如果你想忽略在節點父未發現任何異常,但你還是要附加到根,做如下修改:

if(parentID != 0) 
    { 
     TreeNode foundParentNode; 
     //Note: I changed the if logic from, "not TryGetValue" to "TryGetValue" 
     if (ParentCache.TryGetValue(parentID, out foundParentNode) 
      parentNode = foundParentNode.ChildNodes; 
    } 
+0

謝謝,我已經想出了使用你的代碼的解決方案。只需對緩存進行較小的更改即檢查字典中是否存在關鍵字(否則它會出錯)。 – Jack

+0

@Jack - I更新以包括更多的描述性錯誤消息TryGetValue圖案。 – Todd

+0

感謝@Todd我用:ParentCache.Keys.Contains(的parentID)。猜猜沒有太大的區別。沒有父節點沒問題,所以我沒有添加異常,因爲它應該只是將它添加到根節點。 – Jack

0

檢查了這一點。這不是數據庫驅動,但可能會幫助您構建heirarchical樹。

TreeView tv = new TreeView(); 
private void populateNode() 
{ 

    for(int i=0;i<5;i++) 
    { 
     var parent = new TreeNode(i,string.Format("Node{0}",i)); 
     tv.Nodes.Add(parent); 
     for(int j=0;j<=3;j++) 
     { 
     var child = new TreeNode(j,string.Format("childNode{0}",j) 
     parent.ChildNodes.Add(child); 
     for(int k=0;k<=3;k++) 
     { 
      var grandchild = new TreeNode(k,string.Format("grandchildNode{0}",k) 
      child.ChildNodes.Add(grandchild); 

     } 
     } 
    } 

} 
0

你能不能簡單

  • 創造出具有(讀者環路內)你從你的數據庫中的數據所需要的所有屬性一些自定義對象的列表。
  • 按Rank屬性對列表進行排序
  • 從排序列表中填充treeview?

有點像這樣嗎?

一些結構來存儲你的數據

class TempTreeNode 
{ 
    public int MenuID { get; set; } 
    public int ParentID { get; set; } 
    public int Rank { get; set; } 
    public string Lang { get; set; } 
} 

你的代碼來生成列表:

 var nodeList = new List<TempTreeNode>(); 

     using (var command = new SqlCommand(_Query, _Connection)) 
     { 
      _Connection.Open(); 
      var _Reader = command.ExecuteReader(); 

      while (_Reader.Read()) 
      { 
       var node = new TempTreeNode() 
       { 
        MenuID = (int)_Reader["MenuID"], 
        ParentID = (int)_Reader["ParentID"], 
        Rank = (int)_Reader["Rank"], 
        Lang = _Reader["English"].ToString() 
       }; 
       nodeList.Add(node); 
      } 
      _Connection.Close(); 
     } 
     // sorting 
     nodeList.Sort((a, b) => a.Rank.CompareTo(b.Rank)); 
     // creation 
     CreateNodes(nodeList); 

生成節點...只是猜測你想要什麼方法,所以這不是完成...

private List<TreeNode> CreateNodes(List<TempTreeNode> nodes) 
    { 
     var rootNodes = new List<TreeNode>(); 
     foreach (var node in nodes) 
     { 
      if (node.ParentID == -1) 
      { 
       TreeNode _Node = new TreeNode(node.Lang, node.MenuID.ToString()); 
       rootNodes.Add(_Node); 
      } 
      [...] do whatever... 
     } 
     return rootNodes; 
    }