FindAncestor
是在Window的整个可视树中搜索元素吗?
如果是,那我该如何改进呢?
如果我们通过使用Find Ancestor查找元素并且不存在这样的元素来访问对象的属性,是否会抛出binding data error
?
如果是,那么我该如何解决这样的错误。
在我的情况下,绑定(bind)错误抛出在输出窗口上。为了解决此错误,我尝试设置FallbackValue
,但是现在它给了我警告,而不是唯一的区别是错误。其他一切都与错误相同。
有人可以告诉我FindAncestor
到底如何工作吗?
最佳答案
如果您想知道FindAncestor
在内部如何工作,则应阅读内部代码。 http://referencesource.microsoft.com/#PresentationFramework/Framework/MS/Internal/Data/ObjectRef.cs,6a2d9d6630cad93d
您应该尝试不要过多使用 FindAncestor
。这可能很慢,而且 children 不应该依赖“ parent 那里有我需要的东西”这一已知知识。
就是说,FindAncestor
本身有时也可以是您的 friend 。
这取决于您的情况,但是例如,通常有一个DataGridRow
使用FindAncestor
来查找有关DataGrid
或其他父元素的信息。
问题在于:它 super 慢。假设您有1000个DataGridRows,并且每一行都使用FindAncestor
,加上每一行有7列,它们本身必须遍历逻辑树中的〜200个元素。不必太慢,DataGridRow
始终具有相同的父DataGrid
,可以轻松地对其进行缓存。也许“一次性缓存的relativeSources”将成为新概念。
这个概念可以像这样:完成后编写自己的relativeSource绑定(bind)。首次完成绑定(bind)后,请使用可视树帮助器查找特定类型的父级。如果这样做,则可以将找到的父级存储在直接父级Attachewd属性中,如下所示:
var dic = myElementThatUsesRelativeSourceBinding.Parent.
GetCurrentValue(MyCachedRelativeSourceParentsProperty)
as Dictionary<Type, UIElement>;
dic[foundType] = actualValue;
以后,您可以在以后的相对源搜索中使用此缓存信息。与其取O(n),不如取父对象的相同元素/子代为O(1)。
如果您知道父代始终存在,则应为每个尝试使用
FindAncestor
的元素在代码背后创建绑定(bind)。这样,您可以避免遍历树。您还可以创建一个混合解决方案,该解决方案跟踪可视化树的更改,并维护“缓存”。如果
DataGridRow
要求“找到类型为DataGrid
的相对源”,则没有理由总是需要这样做:可以对其进行缓存。有OnVisualChildrenChanged
-只是一个想法,甚至不能100%地确定它能否很好地完成,但这将需要额外的内存和字典。这可能会变得非常复杂,不用说:-),但是对于“附带项目”将是很酷的。
另一方面您还应该展平视觉树,这会提高您的速度。
关于wpf - 如何提高RelativeSource FindAncestor的性能?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27601961/