如果你想知道FindAncestor
内部是如何工作的,你应该阅读内部代码。http://referencesource.microsoft.com/#PresentationFramework/Framework/MS/Internal/Data/ObjectRef.cs,6a2d9d6630cad93d
您应该尝试不要使用 FindAncestor
那么多。它可能会很慢,而且孩子们不应该依赖“在某个地方有一个父母有我需要的东西”的知识。
也就是说,FindAncestor
它有时也可以成为你的朋友。
这取决于您的情况,但例如,通常DataGridRow
使用 whichFindAncestor
来查找有关DataGrid
或某些其他父元素的信息。
问题在于:它非常慢。假设您有 1000 个 DataGridRows,每行使用FindAncestor
,加上每行有 7 列,它本身必须遍历逻辑树中的约 200 个元素。它不必很慢,DataGridRow
始终具有相同的父级DataGrid
,可以轻松缓存。也许“一次性缓存的 relativeSources”将是一个新概念。
这个概念可以是这样的:编写你自己的 relativeSource 绑定。第一次完成绑定后,使用可视化树助手查找特定类型的父级。如果这样做了,您可以将找到的父级存储在直接父级 attachewd 属性中,如下所示:
var dic = myElementThatUsesRelativeSourceBinding.Parent.
GetCurrentValue(MyCachedRelativeSourceParentsProperty)
as Dictionary<Type, UIElement>;
dic[foundType] = actualValue;
稍后,您在稍后搜索相关源时使用此缓存信息。而不是采用 O(n),而是采用 O(1) 来处理父级的相同元素/子级。
如果您知道父级始终存在,您应该在代码隐藏中为每个尝试使用的元素创建绑定FindAncestor
。这样可以避免遍历树。
您还可以创建一个混合解决方案来跟踪视觉树的变化,并维护“缓存”。如果 aDataGridRow
要求“find me relative source off type DataGrid
”,你没有理由一直这样做:你可以缓存它。有OnVisualChildrenChanged
- 只是一个想法,甚至不能 100% 确定它是否可以很好地完成,但这需要额外的内存和字典。
这可能会变得非常复杂,不用说:-),但对于“副业”来说会很酷。
在另一边;您还应该展平视觉树,它会提高您的速度。