TreeView 中的分层数据。在树中查找节点
Hierarchical Data In TreeView. Find an node in tree
我有一个 TreeView
在其中显示分层数据。
型号
class Node : INotifyPropertyChanged
{
public string Name { get; set; }
public ObservableCollection<Node> Nodes { get; set; } = new ObservableCollection<Node>();
}
节点存储:
class NodesStorage : ObservableCollection<Node>
{
public NodesStorage()
{
var node = new Node { Name = "1" };
node.Nodes.Add(new Node { Name = "1a" });
node.Nodes.Add(new Node { Name = "1b" });
node.Nodes.Add(new Node { Name = "1c" });
var node1 = new Node { Name = "2" };
node1.Nodes.Add(new Node { Name = "2a" });
node1.Nodes.Add(new Node { Name = "2b" });
node1.Nodes.Add(new Node { Name = "2c" });
this.Add(node);
this.Add(node1);
}
}
视图模型
class MainWindowViewModel
{
public MainWindowViewModel()
{
Nodes = new NodesStorage();
}
public ObservableCollection<Node> Nodes;
}
查看
<!--... Set DataContext ...-->
<TreeView ItemsSource="{Binding Path=Nodes}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Nodes}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<!--...-->
问题
现在我想创建 returns true
的方法,如果树包含具有以下名称的节点,在另一种情况下 false
:
public static bool IsTreeContains(Node node, string itemName)
{
if (node.Name == itemName)
return true;
foreach (var n in node.Nodes)
{
return IsTreeContains(n, itemName);
}
// And what should I write here?
}
我想我可以在这里使用回溯。但这是一个非常糟糕的主意。
你怎么看?
你的递归方法有问题:
foreach (var n in node.Nodes)
{
return IsTreeContains(n, itemName);
}
returns
使得循环只执行一次。
这是我的代码:
public static bool IsTreeContains(Node node, string itemName)
{
if (node.Name == itemName)
return true;
foreach (var n in node.Nodes)
{
if(IsTreeContains(n, itemName))
return true;
}
return false;
}
先退出条件,如果找到则停止迭代,如果没有则继续迭代。 最后 如果节点和每个 n-child 与搜索的项目不同,return false
.
希望对您有所帮助。
我能感觉到你在做 "kind of" 树中的深度优先搜索。
要逃避递归,您需要成功和失败两个条件,并且结果必须通过递归传播给调用者。
public static bool IsTreeContains(Node node, string itemName)
{
// If the current Node matches
if (node.Name == itemName)
return true;
// End of the Tree or the Node Collection
if (node.Nodes.Count == 0)
return false;
foreach (var n in node.Nodes)
{
if (IsTreeContains(n, itemName))
return true;
}
return false;
}
我想我刚刚完成了你的解决方案,但是有很多算法可以解决这个问题。
希望这对您有所帮助。
编辑:
根据评论修正了正确的算法。
编辑 1:
更正了仅在第一个子节点上运行的循环。谢谢@BionicCode。
我有一个 TreeView
在其中显示分层数据。
型号
class Node : INotifyPropertyChanged
{
public string Name { get; set; }
public ObservableCollection<Node> Nodes { get; set; } = new ObservableCollection<Node>();
}
节点存储:
class NodesStorage : ObservableCollection<Node>
{
public NodesStorage()
{
var node = new Node { Name = "1" };
node.Nodes.Add(new Node { Name = "1a" });
node.Nodes.Add(new Node { Name = "1b" });
node.Nodes.Add(new Node { Name = "1c" });
var node1 = new Node { Name = "2" };
node1.Nodes.Add(new Node { Name = "2a" });
node1.Nodes.Add(new Node { Name = "2b" });
node1.Nodes.Add(new Node { Name = "2c" });
this.Add(node);
this.Add(node1);
}
}
视图模型
class MainWindowViewModel
{
public MainWindowViewModel()
{
Nodes = new NodesStorage();
}
public ObservableCollection<Node> Nodes;
}
查看
<!--... Set DataContext ...-->
<TreeView ItemsSource="{Binding Path=Nodes}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Nodes}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<!--...-->
问题
现在我想创建 returns true
的方法,如果树包含具有以下名称的节点,在另一种情况下 false
:
public static bool IsTreeContains(Node node, string itemName)
{
if (node.Name == itemName)
return true;
foreach (var n in node.Nodes)
{
return IsTreeContains(n, itemName);
}
// And what should I write here?
}
我想我可以在这里使用回溯。但这是一个非常糟糕的主意。
你怎么看?
你的递归方法有问题:
foreach (var n in node.Nodes)
{
return IsTreeContains(n, itemName);
}
returns
使得循环只执行一次。
这是我的代码:
public static bool IsTreeContains(Node node, string itemName)
{
if (node.Name == itemName)
return true;
foreach (var n in node.Nodes)
{
if(IsTreeContains(n, itemName))
return true;
}
return false;
}
先退出条件,如果找到则停止迭代,如果没有则继续迭代。 最后 如果节点和每个 n-child 与搜索的项目不同,return false
.
希望对您有所帮助。
我能感觉到你在做 "kind of" 树中的深度优先搜索。
要逃避递归,您需要成功和失败两个条件,并且结果必须通过递归传播给调用者。
public static bool IsTreeContains(Node node, string itemName)
{
// If the current Node matches
if (node.Name == itemName)
return true;
// End of the Tree or the Node Collection
if (node.Nodes.Count == 0)
return false;
foreach (var n in node.Nodes)
{
if (IsTreeContains(n, itemName))
return true;
}
return false;
}
我想我刚刚完成了你的解决方案,但是有很多算法可以解决这个问题。
希望这对您有所帮助。
编辑: 根据评论修正了正确的算法。
编辑 1: 更正了仅在第一个子节点上运行的循环。谢谢@BionicCode。