3

我需要从一个数据库表中创建一个菜单结构,该表使用一个 ID 和一个 ParentID 以及一个用于确定节点顺序的 Rank。

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

目前这不是按等级对节点进行排序

我希望输出 HTML 类似于以下内容:

<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/

4

3 回答 3

1

使用字典,这样你就不必痛苦地扫描你的树来寻找父母:

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;
    }
于 2013-09-30T14:09:26.340 回答
0

你不能简单吗

  • 创建一些自定义对象的列表,这些对象具有您从数据库数据中需要的所有属性(在阅读器循环中)。
  • 按 Rank 属性对列表进行排序
  • 从排序列表中填充树视图?

像这样?

一些存储数据的结构

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;
    }
于 2013-09-27T09:49:25.843 回答
0

看一下这个。这不是数据库驱动的,但可能会帮助您构建层次结构树。

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

        }
      }
   }

}
于 2013-09-27T09:33:26.963 回答