Рекурсивное добавление узла в a.NET TreeView



Мне нужно создать структуру меню, взятую из таблицы базы данных, которая использует ID и ParentID и ранг, который используется для определения порядка узлов.



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 и создания этой древовидной структуры,но я не уверен, как обрабатывать глубину добавления. Я могу добавить первый слой узлов, просто проверив, есть ли у них Родительский код, я могу добавить второй слой узлов в условии 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/

659   3  

3 ответов:

Используйте словарь, чтобы вам не пришлось мучительно сканировать дерево в поисках родителя:

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

Проверьте это. Это не управляется базой данных, но может помочь вам в построении дерева 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);

        }
      }
   }

}

Разве ты не можешь просто

  • Создайте список некоторых пользовательских объектов, которые имеют все необходимые свойства из данных вашей базы данных (в цикле чтения).
  • сортировка списка по свойству ранга
  • заполнить 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;
    }

Comments

    Ничего не найдено.