面板在渲染时间和性能方面的效率最高?
有很多时候,多个面板适合我想要的布局,但是我知道不同面板类型的渲染时间有所不同。
例如,MSDN指出
一个相对简单的Panel
,比如Canvas
,可以比一个更复杂的Panel
(比如Grid
具有更好的性能。
那么就渲染时间和性能而言,WPF面板的效率是什么?
WPF专家组:
Canvas
DockPanel
Grid
UniformGrid
StackPanel
WrapPanel
VirtualizingPanel
/ VirtualizingStackPanel
我确信我在网上看到了这个列表,但我现在找不到它。
我正在寻找的理想答案将为我提供一个按顺序排列的面板列表,以便他们渲染速度最快。 我知道孩子的数量是面板有效率的一个重要因素,所以为了这个问题,假设每个面板只有一个Label
/ TextBox
对。
另外,我想列举一些例外情况,例如特定面板在某些条件下表现比其他面板更好。
更新
基于以下接受的答案进行总结,专家组表现基于子项目的数量和布局,然而总的来说,从最快到最慢的列表是:
Canvas
StackPanel
WrapPanel
DockPanel
Grid
另外,如果有很多项目并不总是适合屏幕,则应始终使用VirtualizingPanel
/ VirtualizingStackPanel
。
我强烈建议您阅读下面接受的答案以获取更多详细信息,然后再从此列表中选择一个项目。
我认为描述每个面板的性能特征比试图给出绝对的相对性能比较更简洁和可以理解。
呈现内容时,WPF进行两次传递:度量和排列。 每个面板对于这两个过程中的每一个都有不同的性能特征。
测量通的性能影响最大的面板的,以适应拉伸使用比对(在的情况下,或自动的能力Grid
),然后其被拉伸或自动调整大小的孩子的数目。 安排通行证的表现受到不同儿童的布局位置之间的相互作用的复杂性以及当然儿童的数量的影响。
有时候,给定的面板不容易适应所需的布局。 我创建了一个需要任意数量的项目的控件,每个项目都被放置在可用空间的某个百分比处。 没有一个默认控件可以做到这一点。 试图让他们这样做(通过绑定到父母的实际大小)导致可怕的表现。 我创建了一个基于Canvas的布局面板,它以最少的工作达到了我想要的效果(我复制了画布的源代码并修改了大约20行)。
可用面板:
帆布
定义一个区域,您可以在其中通过相对于“画布”区域的坐标明确定位子元素。
由于每个项目都是静态分配一个位置,因此Canvas在布置过程中的所有面板都具有最佳性能。 由于这个小组没有拉伸的概念,因此测量过程也具有优异的性能; 每个孩子只是使用其原始大小。
DockPanel中
定义一个区域,您可以在其中安排水平或垂直子元素相对于彼此的区域。
Dockpanel有一个非常简单的布局方案,其中相对于添加的前一个项目逐个添加项目。 默认情况下,高度或宽度由项目的原始大小决定(分别基于顶部/底部与左/右),另一个方向由Dock
属性确定,如果宽度或高度未定义。 中等速度通过中等速度安排通过。
格
定义一个由列和行组成的灵活网格区域。
如果使用比例尺寸调整或自动调整大小,这可能是性能最密集的面板。 计算子项目大小可以是项目本地大小和网格指定的布局的复杂组合。 布局也是所有面板中最复杂的。 测试通过的速度慢到中等性能,安排通过速度慢到中等性能。
StackPanel中
将子元素排列成可以水平或垂直取向的单行。
StackPanel使用原生或相对的尺寸来测量它的孩子,方向与它的方向相反,并且它的方向与原生尺寸相对(在这个方向上对齐没有任何作用)。 这使得它成为这个领域的中等水平。 安排通行证是简单的,只是按顺序布置项目。 这可能是本次比赛的第二好成绩。 度量传递的中等性能和布局传递的快速性能。
VirtualizingPanel
为面板元素提供虚拟化其子数据集合的框架。 这是一个抽象类。
用于实现您自己的虚拟化面板的基类。 只加载可见项目以防止不必要地使用内存和处理器。 对于多组项目,性能更高。 由于边界检查,适合屏幕的项目的性能可能稍低一些。 SDK只提供了这个的一个子类,即VirtualizingStackPanel
。
WrapPanel
将子元素从左到右放置在顺序位置,将内容分解到包含框边缘的下一行。 随后的排序从上到下或从右到左依次发生,具体取决于Orientation属性的值。
度量传递是一个有点复杂的过程,其中特定行的最大项目确定行的高度,然后该行上的每个项目使用其原生高度(如果有)或行的高度。 布局过程很简单,将每个项目一个接一个地放在一行上,然后在下一个项目没有足够空间时继续到下一行。 中等绩效测量通过。 中等到快速安排通行证。
参考文献:
尽可能使用效率最高的面板
布局过程的复杂性直接基于您使用的面板派生元素的布局行为。 例如,Grid或StackPanel控件比Canvas控件提供更多的功能。 功能增加的代价是性能成本的增加。 但是,如果您不需要Grid控件提供的功能,则应该使用成本较低的替代方法,例如Canvas或自定义面板。
从优化性能:布局和设计
布局系统为儿童系列的每个成员完成两个通行证,一个测量通行证和一个安排通行证。 每个子面板都提供自己的MeasureOverride和ArrangeOverride方法来实现自己的特定布局行为。
在度量过程中,评估Children集合中的每个成员。 该过程从调用Measure方法开始。 此方法在父Panel元素的实现中调用,并且不必显式调用布局才能发生。
首先,评估UIElement的本地大小属性,例如Clip和Visibility。 这会生成一个名为constraintSize的值,并将其传递给MeasureCore。
其次,处理FrameworkElement上定义的框架属性,这会影响constraintSize的值。 这些属性通常描述底层UIElement的尺寸特征,例如其高度,宽度,边距和样式。 每个属性都可以改变显示元素所需的空间。 然后使用constraintSize作为参数调用MeasureOverride。
注意“高度”和“宽度”,“实际高度”和“实际宽度”的属性之间存在差异。 例如,ActualHeight属性是基于其他高度输入和布局系统的计算值。 该值由布局系统本身根据实际渲染过程设置,因此可能稍微落后于作为输入更改基础的属性(例如高度)的设置值。 因为ActualHeight是一个计算值,所以您应该意识到,由于布局系统的各种操作,可能会有多个或增量报告的更改。 布局系统可能正在计算子元素所需的度量空间,父元素的约束等等。 度量传递的最终目标是让孩子确定在MeasureCore调用期间发生的DesiredSize。 DesiredSize值由Measure存储,以便在内容安排过程中使用。
安排通行证首先调用Arrange方法。 在排列过程中,父面板元素会生成一个表示子项边界的矩形。 该值传递给ArrangeCore方法进行处理。
ArrangeCore方法评估子的DesiredSize并评估可能影响元素渲染大小的任何额外边距。 ArrangeCore生成一个arrangeSize,作为参数传递给Panel的ArrangeOverride方法。 ArrangeOverride生成子的最终大小。 最后,ArrangeCore方法会对偏移属性(如边距和对齐)进行最终评估,并将其置于其布局槽中。 孩子不必(并且经常不)填满整个分配的空间。 控制然后返回到父面板和布局过程完成。
从测量和安排儿童
也许这会帮助你。
不仅适用于面板,而且适用于您希望在WPF中制作的每个应用程序。
它总结了WPF绘图和测量性能。
它还为要定位的不同操作系统提供绘图测试应用程序,结果和结论信息。
您提到的面板是布局面板,因此对布局系统的简要介绍表明它不一定只是最高效面板的简单列表,而是您如何使用对效率和性能影响最大的面板。
LayoutSystem_Overview:
最简单的是,布局是一个递归系统,它导致元素的大小,定位和绘制。 更具体地说,布局描述了测量和排列Panel元素的Children集合的成员的过程。 布局是一个密集的过程。 Children集合越大,必须进行的计算次数就越多。 还可以根据拥有该集合的Panel元素定义的布局行为引入复杂性。 一个相对简单的面板,比如Canvas,可以比一个更复杂的面板(比如Grid)具有更好的性能。
每当孩子UIElement改变其位置时,它就有可能通过布局系统触发新的传球。 因此,了解可以调用布局系统的事件很重要,因为不必要的调用可能会导致应用程序性能不佳。 以下描述调用布局系统时发生的过程。
1.儿童UIElement首先通过测量核心属性来开始布局过程。
2.评估FrameworkElement上定义的大小属性,例如宽度,高度和边距。
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仅将对象保存在当前位于父视图的内存中。 因此,在大多数情况下,性能得到显着改善。
优化性能:布局和设计:本文将详细介绍如何高效地构建树,并根据其复杂性给出一个简单的面板列表
画布(最少完成=效率更高,性能更好)
格
其他面板(更复杂=效率更低,性能更差)
其他性能方面的注意事项:提高WPF UI渲染速度的方法
上一篇: In what order are Panels the most efficient in terms of render time and performance?