我正在努力解决一些逻辑问题,因为我需要从数据库中提取树形结构并添加到TreeView
控件。
为了便于解释,我在winforms
中创建了一个小例子
我们说我有一些字符串列表
private List<string> strings;
public Form1()
{
InitializeComponent();
strings = new List<string>
{
"Root1.Parrent1",
"Root1.Parrent2",
"Root1.Parrent3.Child1",
"Root1.Parrent4.Child2",
"Root2.newParrent1.newChild1",
"Root2.newParrent1.newChild2",
"Root2.NewParrent2"
};
}
所以我想区分每个重复的元素,并制作一个看起来像这样的层次结构,注意我有重复的根和parrents(newparrent1)
main root {
root1( root2(
parrent1 newParrent1(
parrent2 --newChild1
parrent3(--child1) --newChild2)
parrent4(--child2) newParrent2)
}
到目前为止,我的逻辑是卡通,我甚至不知道从哪里开始,我不知道一个节点的菜单子节点如何,完成了一些research,但是没有#39}得到答案。
我只为strings
列表的第一项创建了示例,只是为了看看我的逻辑将如何发展。
string[] splitsArray = strings[0].Split('.');
TreeNode node = new TreeNode();
node.Text = splitsArray[0];
//creating sub node
TreeNode subNode = new TreeNode();
subNode.Text = splitsArray[1];
//adding
node.Nodes.Add(subNode);
treeView1.Nodes[0].Nodes.Add(node);
甚至无法看到我如何将这个逻辑放入循环中。 任何建议都有帮助,甚至是伪代码。谢谢你的时间。
答案 0 :(得分:2)
由于将其标记为算法问题,我将仅提供算法并将编码部分作为练习。
首先,您创建一个包含所有节点的字典,其中键是节点名称,值是节点对象
nodes
和父表
Root2.newParrent1.newChild1
然后你遍历所有字符串并拆分部分,为每个部分检查(newParrent1, Root2)
字典中是否存在名称,如果不存在则将其添加到
并将父项添加到父表。例如
(newChild1, newParrent1)
您会将childParent
和childParent
添加到Children
表格
现在你有一个节点和父节点的字典,我们可以开始创建依赖。
您通过我们刚刚创建的(newParrent1, Root2)
表,并将该节点添加到其对应的父级nodes["Root2"].Children.Add(nodes["newParrent1"]);
属性
例如,如果您有{{1}}
你将会{{1}}
哦,我们忘记了根节点了吗?
我也会把它作为锻炼。
答案 1 :(得分:1)
public class Program
{
public static void Main(string[] args)
{
//Your code goes here
Console.WriteLine("Hello, world!");
List<string> strings;
strings = new List<string>()
{
"Root1.Parrent1",
"Root1.Parrent2",
"Root1.Parrent3.Child1",
"Root1.Parrent4.Child2",
"Root2.newParrent1.newChild1",
"Root2.newParrent1.newChild2",
"Root2.NewParrent2"
};
eat e = new eat(strings);
Console.WriteLine(e.root.ToJson());
Console.WriteLine("Press enter to close...");
Console.ReadLine();
}
}
public class eat
{
public node root;
public eat(List<string> l)
{
root = new node("root");
foreach(string s in l)
{
addRow(s);
}
}
public void addRow(string s)
{
List<string> l = s.Split('.').ToList<String>();
node state = root;
foreach(string ss in l)
{
addSoon(state, ss);
state = getSoon(state, ss);
}
}
private void addSoon(node n, string s)
{
bool f = false;
foreach(node ns in n.soon)
{
if (ns.name == s) { f = !f; }
}
if (!f) { n.soon.Add(new node(s)); }
}
private node getSoon(node n,string s)
{
foreach (node ns in n.soon)
{
if (ns.name == s) { return ns; }
}
return null;
}
}
public class node
{
public node(string n)
{
name = n;
soon = new List<node>();
}
public string name;
public List<node> soon;
public string ToJson()
{
String s = "";
s = s + "{\"name\":\"" + name + "\",\"soon\":[";
bool f = true;
foreach(node n in soon)
{
if (f) { f = !f; } else { s = s + ","; }
s = s + n.ToJson();
}
s = s + "]}";
return s;
}
}
这是一个不使用词典的解决方案 我们有一个食客,其任务是处理和堆叠类似节点的对象 然后我们有一个节点来处理管理元素和子节点。
他使用tojson类来验证正确的操作
outpot:
{
"name": "root",
"soon": [
{
"name": "Root1",
"soon": [
{
"name": "Parrent1",
"soon": [
]
},
{
"name": "Parrent2",
"soon": [
]
},
{
"name": "Parrent3",
"soon": [
{
"name": "Child1",
"soon": [
]
}
]
},
{
"name": "Parrent4",
"soon": [
{
"name": "Child2",
"soon": [
]
}
]
}
]
},
{
"name": "Root2",
"soon": [
{
"name": "newParrent1",
"soon": [
{
"name": "newChild1",
"soon": [
]
},
{
"name": "newChild2",
"soon": [
]
}
]
},
{
"name": "NewParrent2",
"soon": [
]
}
]
}
]
}
<强>更新强>
我刚刚在node
类中添加了递归方法,它会返回TreeNode
obj,所以我可以放入TreeView
,谢谢,这是非常有用的
public TreeNode GetRoot(List<node> nodes, TreeNode parrent)
{
foreach (var node in nodes)
parrent.Nodes.Add(GetRoot(node.children, new TreeNode(node.name)));
return parrent;
}
!!!! ---史蒂夫的解决方案更正确,使用词典--- !!!
答案 2 :(得分:1)
如果您正在寻找将这些字符串添加到TreeView
的方法,可以使用以下代码。答案是尽量用最少的代码来做:
treeView1.BeginUpdate();
foreach (var s in strings)
{
TreeNode node = null;
foreach (var text in s.Split('.'))
{
var key = (node == null ? $"{text}" : $"{node.Name}.{text}");
var nodes = (TreeNodeCollection)((dynamic)node ?? (dynamic)treeView1).Nodes;
node = (nodes.Find(key, false)).FirstOrDefault() ?? nodes.Add(key, text);
}
}
treeView1.EndUpdate();
在上面的代码中使用dynamic
的原因是因为TreeView
和TreeNode
都有Nodes
集合。您可以使用动态,也可以使用两个不同的代码分支(if(node == null){...}/else{...}
),它们非常相似。
仅供您参考的信息TreeNodes
集合有一个Find
方法,可让您按键查找节点。答案依赖于在添加时为节点设置键,这使我们可以在以后简单地找到它。