C# - 根据深度值和列表索引创建树状结构

时间:2017-10-04 20:48:45

标签: c# list treeview children

我试图创建一个树状结构。每个类都有一个父字段和子列表,它与父类相同。基本的东西。

这是我使用的课程的基本版本。

public class TreeElement {
    public string name;
    public int depth;
    public int id;

    public TreeElement parent;
    public List<TreeElement> children = new List<TreeElement>();
}

现在,当我获得初始数据时,我将所有这些类都放在一个列表中。我的树视图中的每个项目都在一个大列表中,我可以继续的是深度值和列表中项目的索引。所以列表基本上看起来像这样:

(0) -1
(1)  |- 0
(2)     |-- 1
(3)     |-- 1
(4)     |   |-- 2
(5)     |-- 1

(x)表示列表中的索引。其余的数字是深度值。

现在我的实际问题。我很难根据这些值制作自己的列表,而且我基本上只能在每个孩子中添加一个项目并且兄弟姐妹被忽略的地方。我真的无法找到考虑这些因素的方法。

到目前为止我的代码(这可能是非常错误的):

private List<TreeElement> GenerateTreeStructure(List<TreeElement> baseList)
{
    // Base list is the list I get provided with.
    List<TreeElement> newList = new List<TreeElement>();
    TreeElement root = null;
    TreeElement previousFolder = null;
    int previousdepth = -99;

    for (int i = 0; i < baseList.Count; i++)
    {
        TreeElement currentResource = baseList[i];
        if (currentResource.depth == -1 && ShowRootFolder) // The root folder.
        {
            root = currentResource;
            // (Name, depth, parent)
            newList.Add(new TreeElement("Root", currentResource.depth, null));
            previousFolder = root;
            previousdepth = root.depth;
        }
        else if (!ShowRootFolder && currentResource.depth <= 0)
        {
            // If root folder is not shown, take all the children of the root folder instead.
            if (currentResource.depth != -1)
            {
                previousFolder = new TreeElement(currentResource.name, currentResource.depth, null);
                previousdepth = previousFolder.depth;
                newList.Add(previousFolder);
            }
        }
        else
        {
            if (currentResource.depth > previousdepth)
            {
                TreeElement newResource = new TreeElement(currentResource.name, currentResource.depth, null);
                previousFolder.children.Add(newResource);
                previousdepth = currentResource.depth;
                previousFolder = newResource;
            }
        }
    }

    return newList;
}

我希望这能解释我的问题。我已经坚持了很长一段时间,我希望能得到一些帮助!

由于

2 个答案:

答案 0 :(得分:1)

我在逻辑上发现了两个错误。这是固定代码:

  // Base list is the list I get provided with.
        List<TreeElement> newList = new List<TreeElement>();
        TreeElement root = null;
        TreeElement previousFolder = null;
        int previousdepth = -99;

        for (int i = 0; i < baseList.Count; i++)
        {
            TreeElement currentResource = baseList[i];
            if (currentResource.depth == -1 && ShowRootFolder) // The root folder.
            {
                root = new TreeElement("Root", currentResource.depth, null);
                // (Name, depth, parent)
                newList.Add(root);
                previousFolder = root;
                previousdepth = root.depth;
            }
            else if (!ShowRootFolder && currentResource.depth <= 0)
            {
                // If root folder is not shown, take all the children of the root folder instead.
                if (currentResource.depth != -1)
                {
                    previousFolder = new TreeElement(currentResource.name, currentResource.depth, null);
                    previousdepth = previousFolder.depth;
                    newList.Add(previousFolder);
                }
            }
            else
            {
                if (currentResource.depth > previousdepth)
                {
                    TreeElement newResource = new TreeElement(currentResource.name, currentResource.depth, previousFolder);
                    previousFolder.children.Add(newResource);
                    previousdepth = currentResource.depth;
                    previousFolder = newResource;
                }
            }
        }

        return newList;

在第一个“if”语句中,您创建了新的Root但未将其分配给根对象,因此未将其分配给您在last if语句中使用的previousFolder对象。你也没有在last if语句中将previousFolder对象传递给TreeElement的构造函数,如果你尝试使用父字段从底部转到root元素,它会引起问题。

P.S。代码很奇怪,似乎你刚开始学习。如果我们讨论的是树形结构,我建议您阅读Composite pattern来创建一个与Visitor pattern结合的树以“访问”它。

答案 1 :(得分:1)

为什么要从GenerateTreeStructure函数返回TreeElement列表有点令人费解?你正在树结构吗?你应该只返回rootnode?无论如何,这需要一个带有深度值的列表并从中生成一个树:

public static TreeElement GenerateTreeStructure(List<TreeElement> baseList)
{
    TreeElement root = null;
    if (baseList == null || baseList.Count == 0) return root;

    int baseIdx = -1;

    TreeElement prevNode = null;
    TreeElement parent = null;

    while (baseIdx < baseList.Count - 1)
    {
        baseIdx++;
        TreeElement item = baseList[baseIdx];

        if (item.depth == -1)
        {
            root = new TreeElement("root", -1, null);
            prevNode = root;
            continue;
        }

        if (item.depth == prevNode.depth) parent = prevNode.parent; // same level as prevNode
        else if (item.depth > prevNode.depth) parent = prevNode;    // deeper
        else                                                        // shallower
        {
            parent = prevNode.parent;
            while (parent.depth >= item.depth) parent = parent.parent;
        }

        TreeElement newNode = new TreeElement(item.name, item.depth, parent);
        parent.children.Add(newNode);
        prevNode = newNode;
    }

    return root;
}

// to test
void Traverse(TreeElement branch, int depth)
{
    log(new string('\t', depth) + branch.name);
    foreach (var subBranch in branch.children) Traverse(subBranch, depth+1);
}

Traverse(root, 0);