很多时候,多个面板适合我想要的布局,但我知道不同面板类型的渲染时间有所不同。
例如,MSDN表示
相对简单的
Panel
,例如Canvas
,可能会有很大的影响 比更复杂的Panel
更好的性能,例如Grid
。
那么就渲染时间和性能而言,WPF面板的顺序是最有效的吗?
WPF小组:
Canvas
DockPanel
Grid
UniformGrid
StackPanel
WrapPanel
VirtualizingPanel
/ VirtualizingStackPanel
我很确定我在网上找到了这个列表,但我现在找不到它。
我正在寻找的理想答案将按照他们最快速渲染的顺序为我提供一个面板列表。我知道孩子的数量是面板效率的一个重要因素,因此为了这个问题,假设每个面板只有Label
/ TextBox
对。
此外,我想要一个例外列表,例如特定面板,它们在某些条件下比其他面板表现更好。
更新
根据下面的accepted answer进行总结,面板性能基于子项的数量和布局,但一般来说,从最快到最慢的列表是:
Canvas
StackPanel
WrapPanel
DockPanel
Grid
此外,如果有许多项目并不总是适合屏幕,则应始终使用VirtualizingPanel
/ VirtualizingStackPanel
。
我强烈建议您在从此列表中选择项目之前阅读下面的accepted answer了解更多详情。
答案 0 :(得分:117)
我认为描述每个面板的性能特征比尝试进行绝对相对性能比较更简洁,更容易理解。
WPF在渲染内容时进行两次传递:测量和排列。每个面板对于这两个面板中的每一个都有不同的性能特征。
测量过程的性能受面板适应拉伸的能力的影响最大(使用Grid
时的自动),然后是拉伸或自动调整大小的子项数。编排通行证的表现受到不同儿童的布局位置之间相互作用的复杂性的影响,当然还有儿童的数量。
有时,给定的面板不容易适应所需的布局。我创建了一个控件,需要任意数量的项目,每个项目位于可用空间的特定百分比。没有默认控件执行此操作。试图让他们这样做(通过绑定到父级的实际大小)会导致可怕的性能。我创建了一个基于Canvas的布局面板,它以最少的工作量实现了我想要的结果(我复制了画布的源并修改了大约20行)。
可用面板:
画布
定义一个可以明确定位子项的区域 按坐标相对于画布区域的元素。
Canvas在排列过程中具有所有面板的最佳性能,因为每个项目都是静态分配的位置。测量通过也具有优异的性能,因为在该面板中没有拉伸的概念;每个孩子只使用原生大小。
DockPanel
定义可以在其中排列子元素的区域 水平或垂直,相对于彼此。
Dockpanel有一个非常简单的布局方案,其中相对于添加的上一个项目逐个添加项目。默认情况下,高度或宽度由项目的原始大小决定(分别基于上/下与左/右),如果宽度或高度为Dock
,则另一个方向由VirtualizingStackPanel
属性决定。未定义。中等到快速测量通过和中到快速通过。
网格
定义由列和行组成的灵活网格区域。
如果使用比例尺寸或自动调整大小,这可能是性能最高的面板。计算子项目大小可以是项目的本机大小和网格指定的布局的复杂组合。布局也是所有面板中最复杂的。测量通过的性能从中到低,对于排列通过,性能从慢到中等。
<强>的StackPanel 强>
将子元素排列成可以定向的单行 水平或垂直。
StackPanel使用本机或相对尺寸测量其子节点,其方向与其方向相反,并且在其方向方向上进行原始尺寸调整(对齐在此方向上不起作用)。这使它成为这一领域的中级表演者。安排通行证很简单,只是按顺序布置项目。可能是这次传球的第二好成绩。测量通过的中等性能和布局通过的快速性能。
VirtualizingPanel
为Panel元素提供虚拟化其子数据集合的框架。这是一个抽象类。
用于实现自己的虚拟化面板的基类。仅加载可见项目以防止不必要地使用内存和处理器。对于多组物品,性能更高。由于边界检查,适合屏幕的项目可能性能稍差。 SDK只提供了一个子类{{1}}。
WrapPanel
将子元素从左到右排列在顺序位置,将内容分解到包含框边缘的下一行。后续排序顺序发生 从上到下或从右到左,取决于的值 定向属性。
度量过程是一个有点复杂的过程,其中特定行的最大项目确定行的高度,然后该行上的每个项目使用其原始高度(如果有的话)或行的高度。布局传递很简单,将每个项目一个接一个地放在一行上,然后在没有足够空间容纳下一个项目时继续到下一行。中等绩效测量通过。安排通过中等至快速的表现。
<强>参考文献:强>
尽可能使用效率最高的面板
布局过程的复杂性直接基于布局 您使用的Panel派生元素的行为。例如,网格或 StackPanel控件提供比Canvas更多的功能 控制。这种功能大幅增加的代价是: 性能成本增加更多。但是,如果您不需要 Grid控件提供的功能,您应该使用 较低成本的替代品,例如Canvas或自定义面板。
来自Optimizing Performance: Layout and Design
布局系统为Children的每个成员完成两次传递 收集,测量通行证和安排通行证。每个儿童小组 提供自己的MeasureOverride和ArrangeOverride方法 实现自己特定的布局行为。
在测量过程中,Children集合的每个成员都是 评估。该过程从调用Measure方法开始。这个 在父Panel的实现中调用方法 元素,并且不必显式调用布局 发生。
首先,评估UIElement的原生大小属性,例如 剪辑和可见性。这会生成一个名为constraintSize的值 被传递给MeasureCore。
其次,在FrameworkElement上定义的框架属性是 已处理,会影响constraintSize的值。这些属性 通常描述底层的尺寸特征 UIElement,例如它的高度,宽度,边距和样式。每一个 属性可以更改显示所需的空间 元件。然后使用constraintSize作为a调用MeasureOverride 参数。
注意高度和宽度的属性之间存在差异 和ActualHeight和ActualWidth。例如,ActualHeight property是一个基于其他高度输入的计算值 布局系统。该值由布局系统本身设置,基于 一个实际的渲染过程,因此可能会略微落后于 设置属性的值,例如Height,它是的基础 输入变化。因为ActualHeight是一个计算值,你应该这样做 请注意,可能存在多个或增量报告的更改 由于布局系统的各种操作而导致它。该 布局系统可能正在计算儿童所需的测量空间 元素,父元素的约束等。终极的 措施通过的目标是让孩子确定它 DesiredSize,在MeasureCore调用期间发生。 DesiredSize 值由Measure存储,以便在内容排列过程中使用。
安排传递以调用Arrange方法开始。在此期间 安排传递,父Panel元素生成一个矩形 代表孩子的界限。该值传递给 ArrangeCore方法进行处理。
ArrangeCore方法评估子项的DesiredSize和 评估可能影响渲染大小的任何其他边距 元素。 ArrangeCore生成一个传给的arrangeSize Panel的ArrangeOverride方法作为参数。 ArrangeOverride生成孩子的finalSize。最后, ArrangeCore方法对偏移属性进行最终评估,例如 作为边距和对齐,并将子项放在其布局槽中。 孩子不必(通常也不会)填满整个孩子 分配空间。然后将控制权返回到父面板和 布局过程完成。
答案 1 :(得分:11)
答案 2 :(得分:7)
您提到的面板是布局面板,因此布局系统的简要概述表明,它可能不仅仅是最有效面板的简单列表,而是您如何使用效果最强的面板效率和绩效。
最简单的布局是递归系统,它导致元素的大小,位置和绘制。更具体地说,布局描述了测量和安排Panel元素集合的成员的过程。布局是一个密集的过程。 Children集合越大,必须进行的计算次数越多。还可以基于拥有集合的Panel元素定义的布局行为来引入复杂性。相对简单的Panel(如Canvas)可以比更复杂的Panel(如Grid)具有更好的性能。
每次子UIElement改变其位置时,它都有可能触发布局系统的新传递。因此,理解可以调用布局系统的事件非常重要,因为不必要的调用会导致应用程序性能不佳。下面描述了调用布局系统时发生的过程。
1。 子UIElement首先测量其核心属性,从而开始布局过程。
2。 将评估FrameworkElement上定义的大小调整属性,例如“宽度”,“高度”和“边距”。
3。 应用面板特定的逻辑,例如Dock方向或堆叠方向。
4。 在测量所有儿童后安排内容。
5。 儿童系列画在屏幕上。
6。 如果将其他子项添加到集合中,应用LayoutTransform或调用UpdateLayout方法,则会再次调用该过程。
有关测量和安排儿童的更多信息,请参阅LayoutSystem_Measure_Arrange
布局是一个递归过程。每次调用布局系统时,都会处理Children集合中的每个子元素。因此,在不需要时应避免触发布局系统。以下注意事项可以帮助您获得更好的性能。
请注意哪些属性值更改将强制布局系统进行递归更新。
其值可导致布局系统初始化的依赖项属性标有公共标志。 AffectsMeasure和AffectsArrange提供了有关哪些属性值更改将强制布局系统进行递归更新的有用线索。通常,任何可以影响元素边界框大小的属性都应该将AffectsMeasure标志设置为true。有关更多信息,请参阅依赖项属性概述。
如果可能,请使用RenderTransform而不是LayoutTransform。
LayoutTransform是一种影响用户界面(UI)内容的非常有用的方法。但是,如果变换的效果不必影响其他元素的位置,则最好使用RenderTransform,因为RenderTransform不会调用布局系统。 LayoutTransform应用其转换并强制进行递归布局更新以考虑受影响元素的新位置。
避免对UpdateLayout进行不必要的调用。
UpdateLayout方法强制进行递归布局更新,并且通常不是必需的。除非您确定需要完整更新,否则请依赖布局系统为您调用此方法。
使用大型Children集合时,请考虑使用VirtualizingStackPanel而不是常规StackPanel。
通过虚拟化子集合,VirtualizingStackPanel仅将对象保留在当前位于父ViewPort中的内存中。因此,在大多数情况下,性能都得到了显着提升。
Optimizing Performance: Layout and Design: 本文详细介绍了如何有效地构建树,并根据其复杂性提供了一个简单的面板列表
画布(最少补充文字=效率更高,性能更好)
网格
其他小组(更复杂=效率更低,性能更差)
需要注意的其他性能注意事项: Ways to improve WPF UI rendering speed