【问题标题】:Does UpdateLayout update all child elements as well?UpdateLayout 是否也会更新所有子元素?
【发布时间】:2016-12-07 18:41:11
【问题描述】:

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

加长版

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

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

就我的测试所见,似乎一个元素的子元素的子元素也被更新了。即 UpdateLayout 是递归的。但是,检查文档UIElement.UpdateLayout 我没有看到我希望它提到的内容。此外,因为文档不鼓励我们使用这种方法,除非绝对必要,提到一些优化,我担心在这里测试不是要走的路——每种情况都可能不同。所以总而言之 - 是否保证 UpdateLayout 是递归的?

【问题讨论】:

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


    【解决方案1】:

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

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

    当您将子元素添加到面板时,面板会自行失效,因为面板的大小或位置可能会受到其子元素的影响(我想 StackPanel 和 Grid 是这样,但 Canvas 不是这样)。

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

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

    文档说的很有趣

    UpdateLayout 基本上相当于依次调用 InvalidateMeasure 和 InvalidateArrange。

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

    【讨论】:

      猜你喜欢
      • 2011-12-29
      • 1970-01-01
      • 2015-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-04
      • 1970-01-01
      • 2020-02-21
      相关资源
      最近更新 更多