在渲染时间和性能方面,Panels 的效率最高的顺序是什么?

有很多时候,一个以上的面板会适合我想要的布局,但我知道有不同的面板类型渲染时间的差异。

例如,MSDN指出

一个相对简单的 Panel,如 Canvas,可以有显着 性能优于更复杂的 Panel,如 Grid

那么,就渲染时间和性能而言,WPF 面板的效率最高的顺序是什么?

WPF 小组:

  • Canvas
  • DockPanel
  • Grid
  • UniformGrid
  • StackPanel
  • WrapPanel
  • VirtualizingPanel/VirtualizingStackPanel

我很确定我在网上看到过这个的清单但我现在找不到了。

理想的答案,我正在寻找将为我提供一个面板的顺序,他们将渲染最快的列表。我知道孩子的数量是影响面板效率的一个重要因素,所以为了回答这个问题,假设每个面板只有一个 Label/TextBox对。

此外,我希望列出一些例外情况,例如在某些条件下,某些面板的性能要优于其他面板。

更新

根据下面的 接受的答案总结一下,面板的性能是基于子项目的数量和布局,但一般来说,从最快到最慢的列表是:

  • Canvas
  • StackPanel
  • WrapPanel
  • DockPanel
  • Grid

此外,如果屏幕上有很多项目并不总是适合,应该始终使用 VirtualizingPanel/VirtualizingStackPanel

我强烈建议你阅读下面的 接受的答案,了解更多细节,然后再从这个列表中选择一个项目。

32762 次浏览

你提到的面板是布局面板,所以对布局系统的简要概述表明,它可能不仅仅是一个最有效面板的简单列表,而是你如何使用对效率和性能影响最大的面板。

LayoutSystem _ Overview :

最简单的说,布局是一个递归系统,它导致元素的大小、位置和绘制。更具体地说,布局描述了衡量和安排 Panel 元素的 Children 集合成员的过程。布局是一个密集的过程。Children 集合越大,必须进行的计算次数就越多。还可以根据拥有集合的 Panel 元素定义的布局行为引入复杂性。相对简单的 Panel (如 Canvas)可以比更复杂的 Panel (如 Grid)具有更好的性能。

每次子 UIElement 更改其位置时,都有可能触发布局系统的新传递。因此,了解可以调用布局系统的事件非常重要,因为不必要的调用可能导致应用程序性能较差。下面描述调用布局系统时发生的过程。

1. 子 UIElement 通过首先测量其核心属性来开始布局过程。

2. 计算在 FrameworkElement 上定义的大小调整属性,如 Width、 Height 和 Margin。

3. 应用面板特定的逻辑,如码头方向或堆叠方向。

4. 内容是在所有儿童测量后安排的。

5. 在屏幕上绘制了 Children 集合。

6. 如果向集合中添加了其他 Children、应用了 LayoutTransform 或调用了 UpdateLayout 方法,则将再次调用该流程。

有关儿童测量和排列的更多信息,请参见 布局系统 _ 测量 _ 排列

LayoutSystem _ Performance :

布局是一个递归过程。在布局系统的每次调用期间处理 Children 集合中的每个子元素。因此,在不必要的时候,应该避免触发布图系统。以下注意事项可以帮助您获得更好的性能。

注意哪些属性值的更改将强制布局系统进行递归更新。

其值可能导致布局系统初始化的依赖项属性用公共标志标记。AffectsScale 和 AffectsArrange 提供了有用的线索,说明哪些属性值的更改将强制布局系统进行递归更新。通常,任何可以影响元素边界框大小的属性都应该将 AffectsScale 标志设置为 true。有关更多信息,请参见依赖项属性概述。

如果可能的话,使用渲染变换代替布局变换。

LayoutTransform 是影响用户界面(UI)内容的一种非常有用的方法。但是,如果转换的效果不必影响其他元素的位置,那么最好使用 RenderTransform,因为 RenderTransform 不调用布局系统。布局变换应用它的转换并强制递归布局更新以说明受影响元素的新位置。

避免对 UpdateLayout 进行不必要的调用。

UpdateLayout 方法强制执行递归布局更新,通常不是必需的。除非您确定需要进行完整的更新,否则请依赖布局系统为您调用此方法。

使用大型 Children 集合时,请考虑使用 VirtualizingStackPanel 而不是常规的 StackPanel。

通过虚拟化子集合,VirtualizingStackPanel 只在内存中保留当前位于父视图端口中的对象。因此,在大多数情况下,性能都得到了显著改善。

优化性能: 布局和设计 : 本文将详细介绍如何有效地构建树,并根据面板的复杂性给出一个简单的面板列表

画布(最小复杂度 = 更高效和更好的性能)

网格

其他面板(更复杂 = 效率较低和性能较差)

其他需要注意的性能考虑: 提高 WPF UI 渲染速度的方法

  1. 把所有东西都存起来。笔刷,颜色,几何图形,格式化文本,字形。(例如,我们有两个类: RenderTools 和 TextCache。将每个单元的地址呈现到两个类的共享实例的过程。因此,如果两个图表具有相同的文本,其准备只执行一次。)
  2. 如果你打算长时间使用的话,可以使用冷冻。尤其是几何学。复杂的未冻结几何图形执行 HitTest 的速度极其缓慢。
  3. 选择呈现每个基元的最快方法。例如,有大约6种文本呈现方式,但最快的是 DrawingContext。画符。
  4. 促进容器回收。虚拟化带来了许多性能改进,但是容器将被释放和重新创建,这是默认的。但是通过设置 VirtualizingStackPanel,可以通过回收容器获得更高的性能。虚拟化模式 = “回收”
  5. 给你开始: 对于应用程序可以支持的嵌套数量没有实际的限制,但是,通常最好限制应用程序只使用那些面板,这些面板实际上是您想要的布局所必需的。在许多情况下,Grid 元素可以代替嵌套面板使用,因为它作为布局容器具有灵活性。这样可以通过将不必要的元素排除在树之外来提高应用程序的性能。

我认为描述每个面板的性能特征比试图给出一个绝对的相对性能比较更简洁和易懂。

WPF 在呈现内容时进行两次传递: 度量和排列。每个面板对于这两个通道都有不同的性能特征。

测量传递的性能最受面板能力的影响,以适应拉伸使用对齐(或自动在 Grid的情况下) ,然后的孩子的数量是拉伸或自动大小。安排传递的性能受到不同子节点布局位置之间相互作用的复杂性的影响,当然还受到子节点数量的影响。

有时,给定的面板不容易借给自己所需的布局。我创建了一个控件,它需要任意数量的项,以便将每个项定位在可用空间的某个百分比上。没有一个默认控件这样做。尝试让它们这样做(通过绑定到父级的实际大小)会导致糟糕的性能。我基于 Canvas 创建了一个布局面板,用最少的工作就达到了我想要的效果(我复制了画布的源代码并修改了大约20行)。

可供选择的展板:

  • 画布

    定义可以显式定位子元素的区域 元素相对于 Canvas 区域的坐标。

    由于每个项目都被静态地分配了一个位置,因此 Canvas 在所有面板中对于安排通行证具有最好的性能。测量传递也有出色的性能,因为在这个面板中没有拉伸的概念; 每个孩子只是使用自己的本机大小。

  • DockPanel

    定义一个区域,您可以在其中排列子元素 水平的或垂直的,相对的。

    Dockpanel 有一个非常简单的布局方案,相对于前面添加的项目,逐个添加项目。默认情况下,高度或宽度由项的本机大小决定(分别基于顶部/底部和左/右) ,如果宽度或高度未定义,则其他方向由 Dock属性决定。中快速测量传递和中快速排列传递。

  • 网格

    定义由列和行组成的灵活网格区域。

    如果使用比例调整大小或自动调整大小,这可能是性能最强的面板。计算子项大小可以是项的本机大小和网格指定的布局的复杂组合。布局也是所有面板中最复杂的。测量通道的慢到中等性能和排列通道的慢到中等性能。

  • 堆栈面板

    将子元素排列成可以面向的单行 水平地或垂直地。

    StackPanel 使用与其方向相反的原生或相对大小度量其子级,并使用与其方向相反的原生大小度量其子级(对齐在这个方向上没有任何作用)。这使得它在这个领域处于中等水平。安排通行证很简单,只是按顺序排列项目。可能是这次第二好的表现了。测量孔型的介质性能和布局孔型的快速性能。

  • 虚拟化面板

    为使其子数据集合虚拟化的 Panel 元素提供一个框架。

    用于实现您自己的虚拟化面板的基类。只加载可见项以防止不必要地使用内存和处理器。对于项目集来说,性能要好得多。由于边界检查,对于适合屏幕的项目,性能可能略低一些。SDK 只提供了其中的一个子类 VirtualizingStackPanel

  • WrapPanel

    将子元素按顺序从左到右放置,将内容中断到包含框边缘的下一行。随后的排序按顺序发生 从上到下或从右到左,这取决于 定向属性。

    度量传递是一个有点复杂的传递,其中特定行的最大项确定行的高度,然后该行上的每个项要么使用其本机高度(如果有的话) ,要么使用行的高度。布局传递很简单,将每个项目一个接一个地放在一行上,然后在没有足够的空间放置下一个项目时继续放在下一行上。中等性能测量通过率。中快速性能的安排通行证。

参考文献:

尽可能使用最有效的面板

布局过程的复杂性直接取决于布局 所使用的 Panel 派生元素的行为 StackPanel 控件提供比 Canvas 更多的功能 这种更大的功能增加的价格是一个 更大的性能成本增加。但是,如果你不需要 网格控件提供的功能,您应该使用 成本较低的替代品,如画布或自定义面板。

来自 优化性能: 布局和设计

布局系统为每个孩子的成员完成两次传球 收集、计量通行证和排列通行证 提供其自己的拳头指令重写和安排重写方法 实现自己特定的布局行为。

在度量值传递期间,Children 集合的每个成员都是 这个过程从一个测量方法的调用开始 方法在父 Panel 的实现中调用 元素,并且不必显式调用以进行布局 发生。

首先,计算 UIElement 的本机大小属性,如 这将生成一个名为 straintSize 的值,该值是 传递给了测量核心。

其次,在 FrameworkElement 上定义的框架属性是 这些属性会影响 straintSize 的值 通常描述基础的大小特征 元素,例如它的高度、宽度、边距和样式 属性可以更改显示 然后使用 straintSize 作为 参数。

注意: Height 和 Width 的属性之间存在差异 实际高度和实际宽度。例如,实际高度 属性是基于其他高度输入和 该值由布局系统本身设置,基于 一个实际的呈现传递,因此可能稍微落后于 属性(如 Height)的设置值,这些属性是 因为实际高度是一个计算值,所以您应该 请注意,可能会有多个或增量报告的变更 由于布局系统的各种操作 布局系统可以计算子所需的测量空间 元素、父元素的约束等等 测量通过的目标是让孩子确定它的 调用时发生 值存储在“度量”中,以便在内容排列传递过程中使用。

安排传递以对 Arrange 方法的调用开始 安排传递时,父 Panel 元素生成一个矩形,该矩形 表示子级的边界。此值被传递给 用于处理的 CompanceCore 方法。

方法计算子级的 DesiredSize 和 计算可能影响呈现的大小的任何附加边距 这个元素会生成一个 changeSize,它被传递给 方法作为参数。 将生成子级的 finalSize 方法执行偏移量属性的最终计算,如 作为边距和对齐方式,并将子元素放入其布局槽中。 孩子不需要(而且经常不需要)填满整个 控件然后返回到父 Panel 和 布局程序已完成。

来自 测量和安排儿童

也许 这个能帮到你。

不仅适用于面板,还适用于您希望在 WPF 中编写的每个应用程序。

总结了 WPF 的绘图和测量性能。

它还提供了您想要针对的不同操作系统的绘图测试应用程序、结果和结论信息。