遍历树并在 C# 中获取某些子项
Iterating through a Tree and getting certain children in C#
我目前正在使用这样定义的树结构
public class TreeNode
{
private ObservableCollection<TreeItem> nodeItems;
private ObservableCollection<TreeNode> nodeChildren;
//public "NodeItems" and "NodeChildren" getters and setters
}
public class TreeItem
{
private bool isSelected;
private string Name;
//public "IsSelected" and "Name" getters and setters
}
public class Tree
{
private TreeNode rootNode;
//public getters and setters properties
}
我正在尝试编写一个函数或 public
属性 递归地获取 Tree
中具有 isSelected == true
的所有 nodeItems
并使其成为平面集合。
所以我在 TreeNode
class 中写了这个函数,递归地遍历子节点:
public ObservableCollection<TreeItem> SelectedItems()
{
ObservableCollection<TreeItem> tempCollection = new ObservableCollection<TreeItem>();
if (nodeItems != null)
{
foreach (TreeItem item in nodeItems)
{
if (item.IsSelected == true)
{
tempCollection.Add(item);
}
}
}
if (nodeChildren != null)
{
foreach (TreeNode node in nodeChildren)
{
tempCollection.Concat(node.SelectedItem());
}
}
return tempCollection;
}
但它总是returns最后是一个空集合。
我该如何更正它,并可能改进它(通过使用 Lambda 表达式或 属性)?
ObservableCollection
上的 Concat
函数不修改任何参数。您必须将生成的对象分配给您的 tempCollection
.
if (nodeChildren != null)
{
foreach (TreeNode node in nodeChildren)
{
tempCollection = new ObservableCollection<TreeNode>(tempCollection.Concat(node.SelectedItem()));
}
}
编辑: 或者,您可以使用重载私有方法来不使用那么多临时集合:
public ObservableCollection<TreeItem> SelectedItems()
{
ObservableCollection<TreeItem> toReturn = new ObservableCollection<TreeItem>();
SelectedItems(toReturn);
return toReturn;
}
private void SelectedItems(ObservableCollection<TreeItem> tempCollection)
{
if (nodeItems != null)
{
foreach (TreeItem item in nodeItems)
{
if (item.IsSelected == true)
{
tempCollection.Add(item);
}
}
}
if (nodeChildren != null)
{
foreach (TreeNode node in nodeChildren)
{
node.SelectedItems(tempCollection);
}
}
}
您可以将树的定义简化为:
public class Tree : ObservableCollection<Tree>
{
public ObservableCollection<TreeItem> nodeItems;
}
现在您可以这样做了:
public IEnumerable<TreeItem> FlattenIsSelected(Tree tree)
{
return tree.nodeItems.Where(x => x.isSelected)
.Concat(tree.SelectMany(t => FlattenIsSelected(t)));
}
如果您保持当前的定义,这并不困难。
我目前正在使用这样定义的树结构
public class TreeNode
{
private ObservableCollection<TreeItem> nodeItems;
private ObservableCollection<TreeNode> nodeChildren;
//public "NodeItems" and "NodeChildren" getters and setters
}
public class TreeItem
{
private bool isSelected;
private string Name;
//public "IsSelected" and "Name" getters and setters
}
public class Tree
{
private TreeNode rootNode;
//public getters and setters properties
}
我正在尝试编写一个函数或 public
属性 递归地获取 Tree
中具有 isSelected == true
的所有 nodeItems
并使其成为平面集合。
所以我在 TreeNode
class 中写了这个函数,递归地遍历子节点:
public ObservableCollection<TreeItem> SelectedItems()
{
ObservableCollection<TreeItem> tempCollection = new ObservableCollection<TreeItem>();
if (nodeItems != null)
{
foreach (TreeItem item in nodeItems)
{
if (item.IsSelected == true)
{
tempCollection.Add(item);
}
}
}
if (nodeChildren != null)
{
foreach (TreeNode node in nodeChildren)
{
tempCollection.Concat(node.SelectedItem());
}
}
return tempCollection;
}
但它总是returns最后是一个空集合。
我该如何更正它,并可能改进它(通过使用 Lambda 表达式或 属性)?
ObservableCollection
上的 Concat
函数不修改任何参数。您必须将生成的对象分配给您的 tempCollection
.
if (nodeChildren != null)
{
foreach (TreeNode node in nodeChildren)
{
tempCollection = new ObservableCollection<TreeNode>(tempCollection.Concat(node.SelectedItem()));
}
}
编辑: 或者,您可以使用重载私有方法来不使用那么多临时集合:
public ObservableCollection<TreeItem> SelectedItems()
{
ObservableCollection<TreeItem> toReturn = new ObservableCollection<TreeItem>();
SelectedItems(toReturn);
return toReturn;
}
private void SelectedItems(ObservableCollection<TreeItem> tempCollection)
{
if (nodeItems != null)
{
foreach (TreeItem item in nodeItems)
{
if (item.IsSelected == true)
{
tempCollection.Add(item);
}
}
}
if (nodeChildren != null)
{
foreach (TreeNode node in nodeChildren)
{
node.SelectedItems(tempCollection);
}
}
}
您可以将树的定义简化为:
public class Tree : ObservableCollection<Tree>
{
public ObservableCollection<TreeItem> nodeItems;
}
现在您可以这样做了:
public IEnumerable<TreeItem> FlattenIsSelected(Tree tree)
{
return tree.nodeItems.Where(x => x.isSelected)
.Concat(tree.SelectMany(t => FlattenIsSelected(t)));
}
如果您保持当前的定义,这并不困难。