您好我目前有一个TreeView
具有以下结构:
子
TreeView结构基本上可以有 NRootNodes - NChildren ,NRootNodes可以有 NRoots和NChildren ,所以基本上就像Windows资源管理器窗口一样。
我当前的问题是我必须得到所有的父母或根,在这种情况下 Roots / RootN 然后我必须删除所有他们的子节点,在本例中为 Child / ChildN 。最后,我必须只有父节点,然后克隆它们,以便我可以将它们移动到TreeView中的不同位置。
RootNodes有一个唯一的标签 - 文件夹,而ChildNodes有另一个唯一的标签 - 计算,正如我之前所说,我必须摆脱所选的所有计算节点,因此只有所选节点的结构将保留。
基本上我最终必须有这样的东西:
我有一个递归方法"扫描" SelectedNode并获取所有父母:
public List<TreeNode> CollectParentNodes(TreeNodeCollection parentCollection, List<TreeNode> collectedNodes)
{
foreach (TreeNode node in parentCollection)
{
if (!collectedNodes.Contains(node.Parent))
{
collectedNodes.Add(node.Parent);
parentNodeAdded = true;
}
if (node.Level != 0 && node.Tag.ToString() != Enumerations.NodeType.Calculation.ToString())
collectedNodes.Add(node);
if (node.Nodes.Count > 0)
CollectParentNodes(node.Nodes, collectedNodes);
}
parentNodeAdded = false;
return collectedNodes;
}
最后我有一个列表可以容纳所有家长,但我面临的问题是家长还包含他们的后代,在这种情况下是计算
我搜索了Google和StackOverFlow,但我找不到任何帮助,如果已经回答,我会事先道歉。
谢谢。
答案 0 :(得分:2)
您可以为TreeView创建一个返回List
的扩展方法GetAllNodes请记住在代码顶部使用using System.Linq;
public static class Extensions
{
public static List<TreeNode> GetAllNodes(this TreeView tree)
{
var firstLevelNodes = tree.Nodes.Cast<TreeNode>();
return firstLevelNodes.SelectMany(x => GetNodes(x)).Concat(firstLevelNodes).ToList();
}
private static IEnumerable<TreeNode> GetNodes(TreeNode node)
{
var nodes = node.Nodes.Cast<TreeNode>();
return nodes.SelectMany(x => GetNodes(x)).Concat(nodes);
}
}
用法将是:
var result = this.treeView1.GetAllNodes().Where(x => x.Tag == "FOLDER").ToList();
请务必在代码顶部添加扩展程序类的命名空间,无论您希望在何处使用它。
作为示例,您可以将“文件夹”标签的“所有节点”设置为红色前景:
var result = this.treeView1.GetAllNodes().Where(x => (x.Tag as string) == "FOLDER").ToList();
result.ForEach(x => x.ForeColor = Color.Red);
这是一个截图
答案 1 :(得分:1)
这将创建一个新树,其中所选节点为root,哪些子节点仅包含标记为“Folder”的节点。
您需要创建一个复制构造函数(或扩展方法)来深度复制节点,以防止对节点对象的操作影响原始树源:
public TreeNode CollectFolderChildNodes(TreeNode selectedNode)
{
if (selectedNode.Tag == "Calculation")
return null;
// Get all the children that are tagged as folder
var childRootNodes = selectedNode.Children.Where((childNode) => childNode.Tag == "Folder";
// Clone root node using a copy constructor
var newRoot = new TreeNode(selectedNode);
newRoot.Children.Clear();
foreach (var childNode in childRootNodes)
{
// Iterate over all children and add them to the new tree
if (childNode.Children.Any())
{
// Repeat steps for the children of the current child.
// Recursion stops when the leaf is reached
newRoot.Children.Add(CollectFolderChildNodes(childNode));
}
else
{
// The current child item is leaf (no children)
newRoot.Children.Add(new TreeNode(childNode));
}
}
return newRoot;
}
我认为应该这样做,但我没有测试过。但也许至少它背后的想法是明确的。
但正如我之前提到的,也许最好遍历树(使用相同的ItemsSource
)并将属性(例如 IsHidingCalculations )设置为true
,这样只有文件夹将出现。您需要实施ItemsStyle
,并在 IsHidingCalculations 评估为true时使用触发器将项Visibility
设置为Collapsed
。
答案 2 :(得分:0)
要克隆没有子节点的节点,您可以创建如下的扩展方法:
public static TreeNode CloneWithoutChildren(this TreeNode node)
{
return new TreeNode(node.Text, node.ImageIndex, node.SelectedImageIndex)
{
Name = node.Name,
ToolTipText = node.ToolTipText,
Tag = node.Tag,
Checked = node.Checked
}
}
然后:
collectedNodes.Add(node.CloneWithoutChildren());