我有一个通用树节点类ObservableTreeNode<K,V>
,其方法应该遍历树的所有节点并检查它们。我还有两节课:
ElementTreeNode : ObservableTreeNode<string, HierarchyElement>
,和
ElementTreeNodeVisual : ElementTreeNode
。
泛型类看起来像这样:
public class ObservableTreeNode<K, V>
{
public K Key { get; set; }
public V Value { get; set; }
public ObservableCollection<ObservableTreeNode<K, V>> Children { get; set; }
public ObservableTreeNode()
{
this.Children = new ObservableCollection<ObservableTreeNode<K, V>>();
}
public static IEnumerable<T> FindNodeInTree<T>(
T rootNode, Func<T, bool> predicate, bool firstOnly = false
) where T : ObservableTreeNode<K, V>
{
var resultNodes = new List<T>();
var nodeQueue = new Queue<T>();
nodeQueue.Enqueue(rootNode);
while (nodeQueue.Any())
{
T currentNode = nodeQueue.Dequeue();
Debug.WriteLine("Current node key: {0}", currentNode.Key);
if (predicate(currentNode))
{
Debug.WriteLine("Match!");
resultNodes.Add(currentNode);
if (firstOnly)
{
Debug.WriteLine("-FindInContext");
return resultNodes;
}
}
Debug.WriteLine("The current node has {0} children.", currentNode.Children.Count);
foreach (T n in currentNode.Children)
{
Debug.WriteLine("Enqueue child...");
nodeQueue.Enqueue(n);
}
}
return resultNodes;
}
}
在我的ElementTreeNodeVisual
课程中,我必须使用新版本隐藏Children
属性,否则我的WPF应用程序中的第三方(Infragistics'XamDataTree
)控件将不会枚举子节点。所以我的ElementTreeNodeVisual
类看起来像这样:
public class ElementTreeNodeVisual : ElementTreeNode
{
public bool IsExpanded { get; set; }
public bool IsSelected { get; set; }
public new ObservableCollection<ElementTreeNodeVisual> Children
{
get;
set;
}
public ElementTreeNodeVisual(ElementTreeNode elementTreeNode)
{
this.Children = new ObservableCollection<ElementTreeNodeVisual>();
this.Element = elementTreeNode.Element;
this.Parent = elementTreeNode.Parent;
foreach (ElementTreeNode child in elementTreeNode.Children)
{
this.Children.Add(new ElementTreeNodeVisual(child));
}
}
}
}
我的问题是,当我尝试调用ElementTreeNodeVisual.FindNodeInTree
方法时,该方法似乎看到了基类的Children
属性 - 它没有项目。
这就是我调用方法的方法:
Func<ElementTreeNodeVisual, bool> isExpandedFunc = delegate(ElementTreeNodeVisual node) { return node.IsExpanded; };
foreach (ElementTreeNodeVisual node in _hierarchyNodeVisuals)
{
var expandedNodes = ElementTreeNodeVisual.FindNodeInTree<ElementTreeNodeVisual>(node, isExpandedFunc);
foreach (ElementTreeNode expandedNode in expandedNodes)
{
expandedNodeIds.Add(expandedNode.Key);
}
}
如果我在foreach循环内的node
变量上设置监视,它会显示具有多个子节点的新Children
属性。然而,Debug.WriteLine(...)
方法中的FindNodeInTree
表示有0个孩子。
作为紧急解决方案,我已复制粘贴FindNodeInTree
方法并将T参数更改为where T : ElementTreeNodeVisual
。它的工作方式如下,但最终不应该有任何复制粘贴的代码...
我应该更改(在泛型类或子类中)以使FindNodeInTree
方法在子类上调用它时看到新属性?
答案 0 :(得分:1)
嗯,这是一个有点奇怪的方法,但它应该有效。 首先,在基类中添加虚拟属性集合。例如:
public virtual ObservableCollection<ObservableTreeNode<K, V>> VirtualChildren {
get { return Children; }
}
在您的搜索方法中,将儿童更改为 VirtualChildren :
public static IEnumerable<T> FindNodeInTree<T>(
T rootNode, Func<T, bool> predicate, bool firstOnly = false
) where T : ObservableTreeNode<K, V>
{
var resultNodes = new List<T>();
var nodeQueue = new Queue<T>();
nodeQueue.Enqueue(rootNode);
while (nodeQueue.Any())
{
T currentNode = nodeQueue.Dequeue();
Debug.WriteLine("Current node key: {0}", currentNode.Key);
if (predicate(currentNode))
{
Debug.WriteLine("Match!");
resultNodes.Add(currentNode);
if (firstOnly)
{
Debug.WriteLine("-FindInContext");
return resultNodes;
}
}
Debug.WriteLine("The current node has {0} children.", currentNode.VirtualChildren.Count);
foreach (T n in currentNode.VirtualChildren)
{
Debug.WriteLine("Enqueue child...");
nodeQueue.Enqueue(n);
}
}
return resultNodes;
}
并覆盖 ElementTreeNodeVisual 中的 VirtualChildren 属性:
public override ObservableCollection<ObservableTreeNode<string, HierarchyElement>> VirtualChildren
{
get { return new ObservableCollection<ObservableTreeNode<string, HierarchyElement>>(Children); }
}
当然,每次归还新物品都不是很好。因此,您可以通过虚拟方法替换此属性,或者订阅 ElementTreeNodeVisual 类中的 CollectionChanged 事件子级属性,并将新元素添加到内部集合中例如,实时。