C# 泛型类的方法不';看不见';新';子类的属性
我有一个通用的树节点类C# 泛型类的方法不';看不见';新';子类的属性,c#,generics,inheritance,properties,C#,Generics,Inheritance,Properties,我有一个通用的树节点类ObservateRetreeNode,它的方法应该遍历树的所有节点并检查它们。我还有两门课: ElementTreeNode:ObservateTreeNode,以及 ElementTreeNodeVisual:ElementTreeNode 泛型类如下所示: public class ObservableTreeNode<K, V> { public K Key { get; set; } public V Value { get; set;
ObservateRetreeNode
,它的方法应该遍历树的所有节点并检查它们。我还有两门课:
ElementTreeNode:ObservateTreeNode
,以及
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;
}
}
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));
}
}
}
}
我的问题是,当我尝试调用elementTreeEndevisional.findNodeTree
方法时,该方法似乎看到了基类的子类
属性,而基类没有项。
下面是我如何调用该方法的:
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);
}
}
Func isExpandedFunc=delegate(elementtreeNode){return node.IsExpanded;};
foreach(分层节点设备中的元素树节点)
{
var expandedNodes=elementTreeNode.findNodeTree(节点,isExpandedFunc);
foreach(expandedNodes中的ElementTreeNode expandedNode)
{
expandedNodeId.Add(expandedNode.Key);
}
}
如果我在foreach循环中的节点
变量上设置了一个watch,它将显示新的子节点
属性,其中包含多个子节点。然而,FindNodeInTree
方法中的Debug.WriteLine(…)
表示有0个子级
作为紧急解决方案,我复制粘贴了FindNodeInTree
方法,并将T参数更改为,其中T:ElementTreeNodeVisual
。它是这样工作的,但最终不应该有任何复制粘贴的代码在那里
我应该更改什么(在泛型类或子类中)以使
FindNodeInTree
方法在子类上调用时看到新属性?好吧,这是一个有点奇怪的方法,但应该可以工作。
首先,在基类中添加虚拟财产集合。例如:
public virtual ObservableCollection<ObservableTreeNode<K, V>> VirtualChildren {
get { return Children; }
}
公共虚拟可观察集合虚拟儿童{
获取{返回子项;}
}
在搜索方法中,将儿童更改为虚拟儿童:
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;
}
public override ObservableCollection<ObservableTreeNode<string, HierarchyElement>> VirtualChildren
{
get { return new ObservableCollection<ObservableTreeNode<string, HierarchyElement>>(Children); }
}
公共静态IEnumerable FindNodeTree(
T rootNode,Func谓词,bool firstOnly=false
)式中T:可观测四节点
{
var resultNodes=新列表();
var nodeQueue=新队列();
nodeQueue.Enqueue(rootNode);
while(nodeQueue.Any())
{
T currentNode=nodeQueue.Dequeue();
WriteLine(“当前节点键:{0}”,currentNode.key);
if(谓词(当前节点))
{
Debug.WriteLine(“匹配!”);
resultNodes.Add(当前节点);
如果(仅限第一次)
{
Debug.WriteLine(“-FindInContext”);
返回结果节点;
}
}
WriteLine(“当前节点有{0}个子节点。”,currentNode.VirtualChildren.Count);
foreach(currentNode.VirtualChildren中的tn)
{
Debug.WriteLine(“排队子…”);
节点排队(n);
}
}
返回结果节点;
}
并覆盖元素树设计中的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;
}
public override ObservableCollection<ObservableTreeNode<string, HierarchyElement>> VirtualChildren
{
get { return new ObservableCollection<ObservableTreeNode<string, HierarchyElement>>(Children); }
}
public override ObservableCollection虚拟儿童
{
获取{returnnewobserveCollection(Children);}
}
当然,每次在属性中返回新集合不是很好。因此,您可以使用虚拟方法替换此属性,也可以订阅ElementTreeEndevisional类中的CollectionChangedeventChildren属性,并实时向内部集合添加新元素,例如。当通过对基类的引用访问基类方法或属性时,新修饰符不会隐藏该方法或属性。@AluanHaddad我知道这一点,但我假设当我显式调用泛型方法as时,T将是方法内部的ElementTreeEndevisional。如果这个假设是错误的,我们将如何解决这个问题?谢谢!与在子类中复制粘贴相同的方法相比,这仍然是一个非常优雅的解决方案。太糟糕了,WPF控制要求我们做这样的黑客。谢谢你们提出的有趣的问题。