我有一个从数据库表加载的数据表,其中包含要加载到treeView中的元素。
数据库表如下所示:
+--------+---------+-------------------------------+
|liv | cod | des |
|--------+---------+-------------------------------+
| 1 | AAA | PANE E SOSTITUTIVI |
| 2 | AAAA |GRISSINI - CRACKERS E SIMIL |
| 3 | AAAA | MAIS |
| 4 | AAAA B | BIANCO |
| 4 | AAAA I | INTEGRALE |
| 3 | AAAAA | AVENA |
| 4 | AAAAAB | BIANCO |
| 4 | AAAAAI | INTEGRALE |
| 3 | AAAAB | ALTRO |
| 4 | AAAABB | BIANCO |
| 4 | AAAABI | INTEGRALE |
| 3 | AAAAF | FARRO |
| 4 | AAAAFB | BIANCO |
| 4 | AAAAFI | INTEGRALE |
| 3 | AAAAK | KAMUT |
| 4 | AAAAKB | BIANCO |
| 4 | AAAAKI | INTEGRALE |
| 3 | AAAAR | FRUMENTO |
| 4 | AAAARB | BIANCO |
| 4 | AAAARI | INTEGRALE |
| 3 | AAAAS | RISO |
| 4 | AAAASB | BIANCO |
| 4 | AAAASI | INTEGRALE |
| 2 | AAAC | ESTRUSI |
| 3 | AAACA | MAIS |
+--------+---------+-------------------------------+
由于树的最大级别(liv)是5,这里是我正在使用的函数将数据表加载到TreeView中:
public void loadFromDataTable(DataTable table, TreeView tree) {
DataView view1 = new DataView(table);
view1.RowFilter = "liv = 1";
foreach (DataRowView dr in view1) {
TreeNode root = new TreeNode(dr["des"].ToString());
DataView view2 = new DataView(table);
view2.RowFilter = "liv = 2 AND cod LIKE '" + dr["cod"].ToString().Trim() + "%'";
foreach (DataRowView dr2 in view2) {
TreeNode root2 = new TreeNode(dr2["des"].ToString());
DataView view3 = new DataView(table);
view3.RowFilter = "liv = 3 AND cod LIKE '" + dr2["cod"].ToString().Trim() + "%'";
foreach (DataRowView dr3 in view3) {
TreeNode root3 = new TreeNode(dr3["des"].ToString());
DataView view4 = new DataView(table);
view4.RowFilter = "liv = 4 AND cod LIKE '" + dr3["cod"].ToString().Trim() + "%'";
foreach (DataRowView dr4 in view4) {
TreeNode root4 = new TreeNode(dr4["des"].ToString());
DataView view5 = new DataView(table);
view5.RowFilter = "liv = 5 AND cod LIKE '" + dr4["cod"].ToString().Trim() + "%'";
foreach (DataRowView dr5 in view5) {
TreeNode root5 = new TreeNode(dr5["des"].ToString());
root4.Nodes.Add(root5);
}
root3.Nodes.Add(root4);
}
root2.Nodes.Add(root3);
}
root.Nodes.Add(root2);
}
tree.Nodes.Add(root);
}
我想知道是否有更好的方法来避免使用这五个嵌套循环。任何面向对象的方法?
感谢您的帮助。
答案 0 :(得分:2)
您可以使用递归来添加节点:
private TreeNode[] GetNodes(DataTable table, int level = 1, string code = "")
{
return table.AsEnumerable()
.Where(row => row.Field<int>("liv") == level
&& row.Field<string>("cod").StartsWith(code))
.Select(row =>
{
var node = new TreeNode(row.Field<string>("des"));
node.Nodes.AddRange(GetNodes(table, level + 1, row.Field<string>("cod")));
return node;
})
.ToArray();
}
使用非常简单:
treeView.Nodes.AddRange(GetNodes(table));
此代码也适用于可变树深度 - 只有在当前级别找到节点时才会更深入。 BTW如果datatable很大,那么考虑延迟加载子节点。在这种情况下,您也可以使用上面的方法,但不需要递归调用。
答案 1 :(得分:1)
这样的东西应该有用(我没有编译/运行代码,但它应该给你一个好主意):
private int _maxDepth = 5;
public void loadFromDataTable(DataTable table, TreeView tree)
{
DataView view1 = new DataView(table);
view1.RowFilter = "liv = 1";
foreach (DataRowView dr in view1)
{
TreeNode node = new TreeNode(dr["des"].ToString());
buildTree(table, node, 2);
tree.Nodes.Add(node);
}
}
public void buildTree(DataTable table, TreeNode parent, int level)
{
if(level <= _maxDepth)
{
DataView view = new DataView(table);
view.RowFilter = "liv = " + level + " AND cod LIKE '" + dr["cod"].ToString().Trim() + "%'";
foreach (DataRowView dr in view) {
TreeNode node = new TreeNode(dr["des"].ToString());
buildTree(table, node, level+1);
parent.Nodes.Add(node);
}
}
}
它仍然看起来非常“hackish”,但它肯定更清洁,更易于维护和更具可扩展性。您还可以查询数据库的最大深度,并且可以以编程方式设置_maxDepth
参数,而不必对其进行硬编码。
我对此感到困惑的一件事:您呈现的代码为子树中的每个节点附加相同的子代。例如:级别2中的每个节点都具有完全相同的子节点,是预期的吗?