面板在渲染时间和性能方面的效率最高?
有很多时候,多个面板适合我想要的布局,但是我知道不同面板types的渲染时间有所不同。
例如, MSDN指出
一个相对简单的
Panel
(如Canvas
)可以比一个更复杂的Panel
(如Grid
具有更好的性能。
那么在渲染时间和性能方面,WPF面板的效率是多less?
WPF小组:
-
Canvas
-
DockPanel
-
Grid
-
UniformGrid
-
StackPanel
-
WrapPanel
-
VirtualizingPanel
/VirtualizingStackPanel
我确信我在网上看到了这个列表,但现在我找不到它了。
我正在寻找的理想答案将为我提供一个按顺序排列的面板列表,以使其渲染速度最快。 我知道孩子的数量是面板效率的一个重要因素,所以为了这个问题,假设每个面板只有一个Label
/ TextBox
对。
另外,我想列举一些例外情况,例如特定的面板,这些面板在某些条件下performance比其他方面好。
更新
根据下面接受的答案总结,专家组的performance是基于子项目的数量和布局,然而总的来说,从最快到最慢的列表是:
-
Canvas
-
StackPanel
-
WrapPanel
-
DockPanel
-
Grid
另外,如果有很多项目不适合在屏幕上,则应始终使用VirtualizingPanel
/ VirtualizingStackPanel
。
我强烈build议您阅读下面接受的答案以获取更多详细信息,然后再从此列表中select一个项目。
我认为描述每个面板的性能特征比试图给出绝对的相对性能比较更简洁和可以理解。
在呈现内容时,WPF进行两次传递:度量和排列。 每个面板对于这两个过程都有不同的性能特点。
度量通过的性能受面板容纳拉伸的能力影响最大(使用alignment方式),然后拉伸或自动resize的孩子的数量。 安排通行证的performance受到不同儿童的布局位置之间的相互作用的复杂性,当然还有孩子的数量的影响。
有时,给定的面板不容易适应所需的布局。 我创build了一个需要任意数量的项目的控件,每个项目都被放置在一定比例的可用空间中。 没有一个默认控件可以做到这一点。 试图让他们这样做(通过绑定到父母的实际大小)导致可怕的performance。 我创build了一个基于Canvas的布局面板,以最less的工作实现了我想要的效果(我复制了canvas的源代码并修改了大约20行)。
可用面板:
-
帆布
定义一个区域,您可以在其中通过相对于“canvas”区域的坐标显式地定位子元素。
由于每个项目都被静态分配一个位置,因此canvas具有布置过程中所有面板的最佳性能。 由于这个小组没有伸展的概念,因此测量通过也有很好的performance。 每个孩子只是使用它的原始大小。
-
DockPanel中
定义一个区域,您可以在其中安排水平或垂直子元素相对于彼此的区域。
Dockpanel有一个非常简单的布局scheme,其中相对于之前添加的项目逐个添加项目。 默认情况下,高度或宽度由项目的原始大小决定(分别基于顶部/底部与左/右),另一个方向由
Dock
属性确定,如果宽度或高度未定义。 中速测量通过中等速度排列通过。 -
格
定义一个由列和行组成的灵活的网格区域。
如果使用比例尺寸调整或自动resize,这可能是性能最密集的面板。 计算子项目大小可以是项目本地大小与网格指定的布局的复杂组合。 布局也是所有面板中最复杂的。 对于测量通过速度慢到中等性能,安排通过速度慢到中等性能。
-
StackPanel中
将子元素排列成可以水平或垂直定位的单行。
StackPanel使用原生或相对的尺寸来定位它的子体,方向与其方向相反,并且在其方向上进行原生尺寸调整(在这个方向上排列没有任何变化)。 这使得它成为这个领域的中等水平。 安排通行证是简单的,只是按顺序布置项目。 可能是这个传球的第二好的performance。 测量通过的中等性能和通过布局的快速性能。
-
VirtualizingPanel
为面板元素提供一个框架,用于虚拟化其子数据集合。 这是一个抽象类。
用于实现您自己的虚拟化面板的基类。 只加载可见的项目,以防止不必要的使用内存和处理器。 对于多组项目,性能更高。 由于边界检查,适合屏幕的项目的性能可能稍低一些。 SDK只提供了这个的一个子类,
VirtualizingStackPanel
。 -
WrapPanel
将子元素从左到右依次放置,将内容分解到包含框边缘的下一行。 随后的sorting从上到下或从右到左依次发生,具体取决于Orientation属性的值。
度量过程是一个有点复杂的过程,其中特定行的最大项目决定行的高度,然后该行上的每个项目使用其原生高度(如果它有一个)或行的高度。 布局过程很简单,将每个项目一个接一个放在一行,然后在下一个项目没有足够空间时继续下一行。 中等性能测量通过。 中等到快速performance为安排通行证。
参考文献:
尽可能使用效率最高的面板
布局过程的复杂性直接基于您使用的Panel派生元素的布局行为。 例如,Grid或者StackPanel控件提供比Canvas控件更多的function。 function的这种更大的增加的价格是性能成本的更大的增加。 但是,如果您不需要网格控件提供的function,则应该使用成本较低的替代方法,如“canvas”或自定义面板。
从优化性能:布局和devise
布局系统完成儿童收集每个成员的两个通行证,一个测量通行证和一个安排通行证。 每个子面板都提供了自己的MeasureOverride和ArrangeOverride方法来实现自己特定的布局行为。
在测量过程中,评估儿童系列的每个成员。 该过程从调用Measure方法开始。 此方法在父面板元素的实现中被调用,并且不必为了布局而显式调用。
首先,评估UIElement的本地大小属性,例如Clip和Visibility。 这将生成一个名为constraintSize的值,并将其传递给MeasureCore。
其次,处理在FrameworkElement上定义的框架属性,这会影响constraintSize的值。 这些属性通常描述底层UIElement的尺寸特征,例如其高度,宽度,边距和样式。 每个属性都可以改变显示元素所需的空间。 然后使用constraintSize作为参数调用MeasureOverride。
注意“高度”和“宽度”,“实际高度”和“实际宽度”的属性有所不同。 例如,ActualHeight属性是基于其他高度input和布局系统的计算值。 该值由布局系统本身根据实际的渲染过程设置,因此可能稍微落后于作为input更改基础的属性(例如高度)的设置值。 由于ActualHeight是一个计算值,因此您应该意识到,由于布局系统的各种操作,可能会有多个或增量报告的更改。 布局系统可能正在计算子元素所需的度量空间,父元素的约束等等。 度量传递的最终目标是让孩子确定在MeasureCore调用期间发生的DesiredSize。 DesiredSize值通过Measure存储,以便在内容安排过程中使用。
安排通行证首先调用Arrange方法。 在排列过程中,父Panel元素生成一个矩形,表示该子项的边界。 这个值被传递给ArrangeCore方法进行处理。
ArrangeCore方法评估子的DesiredSize并评估可能影响元素的渲染大小的任何额外边距。 ArrangeCore生成一个arrangeSize作为parameter passing给Panel的ArrangeOverride方法。 ArrangeOverride生成孩子的最终大小。 最后,ArrangeCore方法会对偏移属性(如边距和alignment)进行最终评估,并将其置于其布局槽中。 孩子不必(并且经常不)填满整个分配的空间。 控制然后返回到父面板和布局过程完成。
从测量和安排儿童
也许这会帮助你。
不仅面板,而且你想要在WPF中创build的每个应用程序。
它总结了WPF的绘图和测量性能。
它还针对您要定位的不同操作系统提供绘图testing应用程序,结果和结论信息。
您提到的面板是布局面板,因此对布局系统的简要介绍表明它不一定只是最高效面板的简单列表,而是您如何使用对效率和性能影响最大的面板。
LayoutSystem_Overview :
最简单的是,布局是一个recursion系统,导致元素的大小,定位和绘制。 更具体地说,布局描述了测量和排列Panel元素的Children集合的成员的过程。 布局是一个密集的过程。 Children集合越大,必须进行的计算次数越多。 也可以根据拥有集合的Panel元素定义的布局行为来引入复杂性。 一个相对简单的Panel(如Canvas)可以比一个更复杂的Panel(如Grid)具有更好的性能。
每当一个孩子UIElement改变其位置,它有可能触发布局系统的新通行证。 因此,了解可以调用布局系统的事件是非常重要的,因为不必要的调用可能会导致应用程序性能不佳。 以下描述调用布局系统时发生的过程。
1.一个孩子UIElement开始布局过程,首先测量其核心属性。
2.评估在FrameworkElement上定义的大小调整属性,例如宽度,高度和边距。
3.应用面板特定的逻辑,例如Dock方向或堆叠方向。
4.所有孩子都被测量后,内容被安排。
5.儿童系列画在屏幕上。
6.如果将额外的子项添加到集合,应用LayoutTransform或调用UpdateLayout方法,则会再次调用该过程。
有关测量和安排儿童的更多信息,请参阅LayoutSystem_Measure_Arrange
LayoutSystem_Performance :
布局是一个recursion的过程。 在每次调用布局系统期间,都会处理Children集合中的每个子元素。 因此,在没有必要的时候,应该避免触发布局系统。 以下注意事项可以帮助您获得更好的性能。
请注意哪些属性值更改将强制布局系统进行recursion更新。
其值可以导致布局系统初始化的依赖属性用公共标志标记。 AffectsMeasure和AffectsArrange提供有用的线索,以确定哪些属性值更改将强制布局系统进行recursion更新。 通常,任何可能影响元素边界框大小的属性都应该有一个AffectsMeasure标志设置为true。 有关更多信息,请参阅依赖项属性概述。
如果可能,请使用RenderTransform而不是LayoutTransform。
LayoutTransform可以是影响用户界面(UI)内容的非常有用的方法。 但是,如果转换的效果不必影响其他元素的位置,则最好使用RenderTransform,因为RenderTransform不会调用布局系统。 LayoutTransform应用其转换,并强制recursion布局更新以说明受影响元素的新位置。
避免对UpdateLayout进行不必要的调用。
UpdateLayout方法强制recursion布局更新,并且通常不是必需的。 除非您确定需要完整更新,否则请依靠布局系统为您调用此方法。
处理大型Children集合时,请考虑使用VirtualizingStackPanel而不是常规的StackPanel。
通过虚拟化子集合,VirtualizingStackPanel仅将对象保存在当前位于父视图的内存中。 因此,在大多数情况下,性能得到大幅改善。
优化性能:布局和devise :本文将详细介绍如何高效地构build树,并根据其复杂性给出一个简单的面板列表
canvas(最less完成=效率更高,性能更好)
格
其他面板(更复杂=效率更低,性能更差)
其他性能注意事项: 提高WPF UI渲染速度的方法
- caching一切。 画笔,颜色,几何,格式化文本,字形。 (例如,我们有两个类:RenderTools和TextCache,每个单元的渲染过程地址都是两个类的共享实例,所以如果两个图表具有相同的文本,则只准备执行一次。
- 冻结Freezable,如果你打算长期使用它。 特别是几何形状。 复杂的解冻几何执行HitTest非常缓慢。
- select最快的方式来渲染每个基元。 例如,大约有6种文本渲染方式,但最快的是DrawingContext.DrawGlyphs。
- 启用容器回收。 虚拟化带来了很多性能改进,但容器将被丢弃并重新创build,这是默认设置。 但是通过设置VirtualizingStackPanel.VirtualizationMode =“Recycling”来回收容器,你可以获得更多的性能。
- 从这里 :你的应用程序可以支持的嵌套数量没有实际的限制,但是,通常最好限制你的应用程序只使用实际需要的那些面板来进行你想要的布局。 在许多情况下,可以使用Grid元素来代替嵌套面板,因为它具有作为布局容器的灵活性。 这可以通过在树中保留不必要的元素来提高应用程序的性能。