2016-12-07 57 views
0

tl; dr将子元素添加到元素时 - 调用theParent.UpdateLayout();时孩子的布局是否会更新?UpdateLayout是否更新所有子元素?

加长版

我需要调用UpdateLayout一个元素上,以获取有关其子属性的一些信息。

theParent.Children.Add(child); 
theParent.UpdateLayout(); 

就我所见,通过我的测试,看起来像元素的孩子的孩子也被更新了。即UpdateLayout是递归的。但是,检查文档UIElement.UpdateLayout我没有看到我所期望的。此外,由于文档不鼓励我们使用这种方法,除非绝对必要,提及一些优化,我担心这里的测试不是要走的路 - 每种情况都可能不同。所以最后 - 是否保证UpdateLayout是递归的?

回答

1

布局系统本质上是递归的。为了使按钮根据其内容自动调整自己的尺寸,它需要首先测量其子元素(即通常是TextBlock标签),并且那些子元素也可能需要测量其子元素,等等。

当您创建一个新的UIElement时,其布局最初是无效的(或“脏”)。这意味着该元素被标记为“需要在下一个布局周期中布局” - 布局系统将跳过未被标记为优化的元素作为优化(布局对于复杂的可视化树尤其昂贵)。

将子元素添加到面板时,面板会自动失效,因为面板的大小或位置可能会受其子级的影响(对于StackPanel和Grid而言是true,但对于Canvas,我想象的是这样)。

理解布局操作是批处理很重要。由于布局过程是一项昂贵的操作,因此最好将其推迟到不再发生元素更新时为止。想象一下,如果您将100个项目添加到ListView中,那么不是每次都执行100次布局更新,而是在将100个项目添加到列表后的某个时间点执行1次更新。

无论如何,回到你的问题,调用UpdateLayout将立即布局任何失效的元素内的子树根植于UpdateLayout被调用的元素,而不是等待直到延迟布局通过。

有趣的是,该文件说

UpdateLayout请基本上等同于调用InvalidateMeasure和InvalidateArrange顺序。

但它似乎并没有实际上使被调用的元素的布局无效,而是它只是强制立即更新已经失效的元素(但这只是我的观察)。他们在这里基本上非常松散地使用。

相关问题