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/

10-10 16:36