UpdateLayout是否也更新所有子元素?

时间:2016-12-07 18:41:12

标签: c# xaml uwp win-universal-app uwp-xaml

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

更长版本

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

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

据我所知,我的测试看起来像一个元素的孩子的孩子也被更新了。即UpdateLayout是递归的。但是,检查文档UIElement.UpdateLayout我没有看到提到的那些我期望它。另外,因为文档不鼓励我们使用这种方法,除非绝对必要,提到一些优化,我担心这里的测试不是要走的路 - 每种情况都可能不同。总而言之 - 是否保证UpdateLayout是递归的?

1 个答案:

答案 0 :(得分:1)

布局系统本质上是递归的。为了让Button根据其内容自动调整大小,它需要首先测量其子元素(即通常是TextBlock标签),而那些子元素也可能需要测量它们的子元素,等等。

创建新的UIElement时,其布局最初会失效(或者#34;脏")。这意味着元素标记为"需要在下一个布局周期中布局" - 布局系统将跳过未标记为脏的元素作为优化(特别是对于复杂的可视树,布局很昂贵)。

当您向面板添加子元素时,面板会使其自身无效,因为面板的大小或位置可能受其子节点的影响(对于StackPanel和Grid,则为true,但对于Canvas,我认为不是这样)。

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

无论如何,回到你的问题,调用UpdateLayout将立即布局以调用UpdateLayout的元素为根的子树中的任何无效元素,而不是等到延迟布局通过。

文档中说

很有意思
  

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

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