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


127

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

例如,MSDN指出

相对简单的Panel(例如)Canvas比复杂的Panel(例如)具有明显更好的性能Grid

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

WPF面板:

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

我相当确定我在网上某个地方看到了此列表,但现在找不到。

我正在寻找的理想答案是按顺序提供面板列表,以使它们以最快的速度呈现。我理解孩子的数量是在面板的效率有多高是一个很大的因素,所以对于这个问题起见,假设每个小组只有一个Label/ TextBox对。

此外,我还希望列出一些例外情况,例如,在某些条件下,某些小组的表现要优于其他小组。

更新资料

根据以下公认的答案进行总结,面板性能取决于子项的数量和布局,但是总的来说,从最快到最慢的列表是:

  • Canvas
  • StackPanel
  • WrapPanel
  • DockPanel
  • Grid

另外,如果有很多项目不总是显示在屏幕上,则应始终使用VirtualizingPanel/ VirtualizingStackPanel

我强烈建议您在从列表中选择一项之前,阅读以下接受的答案以获取更多详细信息。


仅仅假设虚拟化面板的性能总是要比非虚拟化面板好吗?
BoltClock

@BoltClock我认为这取决于面板中有多少不可见的内容。如果有很多不可见的项目,则a的性能VirtualizingStackPanel肯定会更好,但是如果面板中显示的所有项目都是可见的,则比我认为使用常规面板更好。
拉结

谢谢。当所有项目无论如何都将显示时,这确实是浪费虚拟化项目。
BoltClock

除了虚拟化之外,它们具有不同的功能,否则它们将不是单独的控件。我选择了为客户提供最佳UI的东西。
狗仔队2012年

1
您确定除了虚拟化之外还有明显的区别吗?他们要做的就是执行相对轻量级的布局算法。与之后的所有渲染相比,很小。话虽如此,网格可能是最慢的(加权缩放)。
Henk Holterman

Answers:


130

我认为描述每个面板的性能特征比尝试进行绝对的相对性能比较更为简洁和可理解。

WPF在渲染内容时进行两次传递:“测量”和“排列”。每个面板在这两次通过中都有不同的性能特征。

度量通过的性能受面板适应使用对齐方式拉伸的能力(如果为,则为“自动” Grid),然后受拉伸或自动调整大小的子代数目的能力影响最大。排列通过的性能受不同子项的布局位置之间的交互复杂性的影响,然后受子项数量的影响。

有时,给定的面板不容易适应所需的布局。我创建了一个控件,该控件需要将任意数量的项目放置在可用空间的特定百分比处。没有默认控件会执行此操作。试图使他们做到这一点(通过绑定到父母的实际大小)会导致可怕的表现。我基于Canvas创建了一个布局面板,该面板通过最少的工作即可达到我想要的结果(我复制了画布的源代码并对其进行了大约20行修改)。

可用面板:

  • 帆布

    定义一个区域,您可以在其中通过相对于Canvas区域的坐标来显式定位子元素。

    由于对每个项目静态分配了一个位置,因此“画布”在所有通过面板中具有最佳性能。由于该面板没有拉伸的概念,因此测量合格还具有出色的性能。每个孩子仅使用其原始大小。

  • 码头面板

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

    Dockpanel有一个非常简单的布局方案,其中,相对于之前添加的项目,一项一项地添加。默认情况下,高度或宽度取决于项目的原始大小(分别基于上/下与左/右),Dock如果宽度或高度未定义,则另一个方向由属性确定。中速测量通过和中速布置通过。

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

    如果使用比例大小调整或自动大小调整,这可能是性能最高的面板。计算子项目大小可以是项目的原始大小和网格指定的布局的复杂组合。布局也是所有面板中最复杂的。测量阶段的性能慢到中等,而布置阶段的性能慢到中等。

  • 堆栈面板

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

    StackPanel使用与其方向相反的方向的本机或相对大小和沿其方向的本机大小来测量其子项(对齐在该方向上不起作用)。这使其成为该领域的中级表演者。安排通行证很简单,只需按顺序布置物品即可。此通行证可能是第二好的表现。测量阶段的性能为中等,布局阶段的性能为快速。

  • 虚拟化面板

    为虚拟化其子数据集合的Panel元素提供一个框架。这是一个抽象类。

    用于实现自己的虚拟化面板的基类。仅加载可见项,以防止不必要地使用内存和处理器。对于项目集,性能更高。由于进行了边界检查,因此适合屏幕上的项目的性能可能略低。SDK仅提供其中的一个子类VirtualizingStackPanel

  • 包装面板

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

    度量传递是一种比较复杂的传递,其中特定行的最大项目确定该行的高度,然后该行上的每个项目都使用其本机高度(如果有的话)或该行的高度。布局过程很简单,将每个项目一个接一个地放置在一行上,然后在没有足够空间容纳下一个项目时继续到下一行。中等绩效评估合格。中级到快速级的安排成绩。

参考文献:

尽可能使用效率最高的面板

布局过程的复杂性直接取决于您使用的Panel派生元素的布局行为。例如,与Canvas控件相比,Grid或StackPanel控件提供的功能更多。功能上更大的增加所带来的代价是性能成本上的更大增加。但是,如果不需要网格控件提供的功能,则应使用成本较低的替代方法,例如“画布”或自定义面板。

优化性能:布局和设计

布局系统为Childs集合的每个成员完成了两个遍,一个度量遍和一个布置遍。每个子面板提供自己的MeasureOverride和ArrangeOverride方法以实现其特定的布局行为。

在评估通过期间,将评估Children集合的每个成员。该过程始于对Measure方法的调用。在父Panel元素的实现中调用此方法,并且不必显式调用此方法即可进行布局。

首先,评估UIElement的原始大小属性,例如Clip和Visibility。这将生成一个名为constraintSize的值,该值将传递到MeasureCore。

其次,处理在FrameworkElement上定义的框架属性,这会影响ConstraintSize的值。这些属性通常描述基础UIElement的大小特征,例如其高度,宽度,边距和样式。这些属性中的每一个都可以更改显示元素所需的空间。然后使用constraintSize作为参数调用MeasureOverride。

注意高度和宽度属性与ActualHeight和ActualWidth之间存在差异。例如,ActualHeight属性是基于其他高度输入和布局系统的计算值。该值由布局系统本身根据实际的渲染过程设置,因此可能会稍微落后于作为输入更改基础的属性(如Height)的设置值。因为ActualHeight是一个计算值,所以您应该意识到,布局系统进行的各种操作可能会报告多个或增量的更改。布局系统可能正在计算子元素所需的度量空间,父元素的约束等等。度量传递的最终目标是让孩子确定其DesiredSize,这在MeasureCore调用期间发生。Measure存储了DesiredSize值,以在内容整理过程中使用。

整理过程从对Arrange方法的调用开始。在安排过程中,父Panel元素会生成一个表示子边界的矩形。此值将传递给ArrangeCore方法进行处理。

ArrangeCore方法评估子项的DesiredSize,并评估可能影响元素的呈现大小的任何其他边距。ArrangeCore生成一个rangingSize,它作为参数传递给Panel的ArrangeOverride方法。ArrangeOverride生成子项的finalSize。最后,ArrangeCore方法对偏移属性(例如边距和对齐)进行最终评估,并将子项放入其布局槽中。孩子不必(通常不必)填满整个分配的空间。然后将控件返回到父面板,并且布局过程完成。

衡量和安排孩子


1
针对现在已删除的评论:我没有包括指标,因为它们将无济于事。电子表格组合太多,无法使用。优化性能的一种更有用的方法是,使用一般理解来选择初始布局面板,然后根据实际情况进行分析,根据需要从中进行优化。
2012年

谢谢您的解释,实际上是如何渲染WPF面板的,并且每个面板的“度量/排列”性能远远优于我的要求:)
Rachel 2012年

@mydogisbox我UniformGrid在您的列表中都看不到。您能否使用该面板更新您的答案,并评估相对于其他面板类型的“度量/安排”效果?
雷切尔2012年

1
@Rachel UniformGrid不适用于应用程序布局。请参阅此处的“派生面板元素”:msdn.microsoft.com/en-us/library/ms754152.aspx,以获取更多信息。在速度方面,它应该比a快DockPanel一点,但比a慢一点Canvas
2012年

12

也许会对您有所帮助。

不仅适用于面板,还适用于您要在WPF中制作的每个应用程序。

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

它还具有您要定位的不同操作系统的图形测试应用程序,结果和结论信息。


8

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

LayoutSystem_Overview

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

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

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

2.评估在FrameworkElement上定义的大小调整属性,例如Width,Height和Margin。

3.应用特定于面板的逻辑,例如Dock方向或堆叠方向。

4.在对所有孩子进行测量之后,才安排内容。

5.在屏幕上绘制儿童集合。

6.如果将其他子级添加到集合,应用了LayoutTransform或调用UpdateLayout方法,则再次调用该过程。

有关测量和安排子的更多信息,请参见LayoutSystem_Measure_Arrange

LayoutSystem_Performance

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

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

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

如果可能,请使用RenderTransform而不是LayoutTransform。

LayoutTransform是影响用户界面(UI)内容的非常有用的方法。但是,如果变换的效果不必影响其他元素的位置,则最好改用RenderTransform,因为RenderTransform不会调用布局系统。LayoutTransform应用其转换并强制进行递归布局更新以考虑受影响元素的新位置。

避免不必要地调用UpdateLayout。

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

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

通过虚拟化子级集合,VirtualizingStackPanel仅将对象当前保留在父级ViewPort内的内存中。结果,在大多数情况下,性能都得到了显着改善。

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

画布(最少的组合=更有效和更好的性能)

其他小组(更复杂=效率较低且性能较差)

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

  1. 缓存所有内容。笔刷,颜色,几何形状,格式化文本,字形。(例如,我们有两个类:RenderTools和TextCache。每个单元的渲染过程将地址分配给这两个类的共享实例。因此,如果两个图表具有相同的文本,则其准备仅执行一次。)
  2. 如果打算长时间使用,请冻结Freezable。特别是几何形状。复杂的未冻结几何图形执行HitTest的速度非常慢。
  3. 选择最快的渲染每个图元的方法。例如,大约有6种文本呈现方式,但是最快的是DrawingContext.DrawGlyphs。
  4. 启用容器回收。虚拟化带来了很多性能改进,但是容器将被处置并重新创建,这是默认设置。但是通过设置VirtualizingStackPanel.VirtualizationMode =“ Recycling”,可以通过回收容器来获得更高的性能。
  5. 这里开始:对您的应用程序可以支持的嵌套数量没有实际限制,但是,通常最好将您的应用程序限制为仅使用所需布局实际需要的那些面板。在许多情况下,由于其作为布局容器的灵活性,因此可以使用Grid元素代替嵌套面板。通过将不必要的元素保留在树中,可以提高应用程序的性能。

2
这个答案几乎完全由其他来源的复制和粘贴组成,其中一些来源是未知的。如果只将其缩小为相关部分,正确地归因于所有来源,并尝试更直接地回答问题,那就更好了。
2012年

2
@mydogisbox答案是信息的汇编,我可能会添加许多您在答案中使用的相同站点。为了不考虑改变绩效的其他方面,可能会导致答案不完整或提问者仍然有其他问题,因此我选择将它们包括在内。尽管Rachel拥有令人惊叹的21.7K代表和许多WPF经验,他们可能已经知道此信息,但其他正在研究此问题的人可能会希望这些附加的可靠信息以及答案。
埃里克(Erick)2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.