大家知道WPF有多種Panel,如Canvas,Grid,StackPanel,DockPanel,WrapPanel,VirtualizingPanel等。
在一些場景下可以選擇任何一種或多種Panel實現一種效果。本文談一下在同一場景下使用哪種Panel性能會更好。
新建一個WPF項目,各放置Stackpanel,Canvas,Grid,看下所占的內存,如圖1,2,3
圖1 Grid
圖2 Canvas
圖3 StackPanel
我們可以看到空內容情況下內存容量是StackPanel=Canvas<Grid。
查看Panel類的OnRender方法,各類面板的性能差異主要體現在Render的過程中計算(Measure)和排列(Arrange)不同容器內容的功能差異導致的性能消耗。
大家有興趣可以反編譯.NET Framework,閱讀下StackPanel,Canvas,Grid各自的MeasureOverride和ArrangeOverride方法。
1.Measure和Arrange:
在MeasureOverride方法里,影響性能的是自適應Arrange的屬性。舉例:HorizontalAlignment.Strech或Grid中ColumnDefinition的Width="Auto"。
只要設置了這些屬性,則Panel控件的子控件都將會拉伸或者自動計算大小。
在ArrangeOverride方法里,影響性能的是不同的子控件在Panel位置之間的相互作用的復雜度以及子控件的數目。
2.Panel類的派生
在項目中有些特殊需求WPF現有提供的布局控件滿足不了需求,這時候需要我們寫自定義控件。舉例:在ERP應用軟件中大量的數據圖表需要在UI顯示,這時候
我們需要在布局中顯示類似HTML中TABLE 百分比的功能。兩種做法:1.Binding副控件的實際大小通過Converter計算百分比 2.派生自布局控件重寫功能
如果使用方法1通過默認控件Binding,通過Memory Profiler看到其性能表現相當糟糕。
使用方法2.繼承自布局控件,其性能消耗小了很多。
下面我們分別看下Grid,Canvas,StackPanel
1.Grid:
Grid定義一個可設置的的網格區域,可以將該網格區域分割成多行與多列。
如果使用按比例(如:3*,7*)或者Auto調節行列大小,Grid 是一個性能損耗最嚴重的面板控件。
原因是:當VisualTree上Child的原始大小和布局位置通過 Grid 來指定的時候,Child的區域大小計算非常復雜。同時,在所有Panel類型控件中,它的布局過程是最復雜的。
性能評估:它的計算性能和排列性能屬於中低水平。
2.Canvas:
Canvas定義了一個區域內的坐標系,Child可根據該坐標系決定處於布局中的絕對位置。
Canvas 擁有在所有控件中最好的排列(Arrange)性能,在計算(Measure)步驟中也有很好的性能表現。
原因是:針對Arrange,Canvas的所有Child位置都是絕對位置,是固定,直接指定的,Canvas並沒有拉伸(Strech,Uriform,Fill etc...)的屬性,所有Child都是使用自己的原始尺寸。
性能評估:性能最好,無論是計算性能和排列性能。
3.StackPanel:
StackPanel定義了區域內的Child將按照水平方向或垂直方向排列成一行。
在 StackPanel 內,Child的尺寸將如此計算:根據 StackPanel 的排列(Orientation)方向,如:垂直方向,則它的Child在水平方向的尺寸則使用原始尺寸或相對尺寸,而垂直方向的尺寸則使用原始尺寸(對齊屬性在此方向並不影響它的尺寸)。由於它的排列(Arrange)步驟相對簡單,只是將Child按順序的逐個排列,所以它在這步驟的性能在所有Panel控件中排前列。
性能評估:計算(Measure)性能屬於中等水平,排列(Arrange)性能屬於高等水平。
代碼:
1 <Window x:Class="PerformanceDemo.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="MainWindow" Height="350" Width="525"> 5 <!--<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> 6 <Grid.RowDefinitions> 7 <RowDefinition Height="2*"></RowDefinition> 8 <RowDefinition Height="Auto"></RowDefinition> 9 <RowDefinition Height="Auto"></RowDefinition> 10 <RowDefinition Height="Auto"></RowDefinition> 11 </Grid.RowDefinitions> 12 <Grid.ColumnDefinitions> 13 <ColumnDefinition Width="3*"></ColumnDefinition> 14 <ColumnDefinition Width="Auto"></ColumnDefinition> 15 </Grid.ColumnDefinitions> 16 <Label>Test</Label> 17 <TextBlock Grid.Column="1">Test</TextBlock> 18 <TextBlock Grid.Row="1" Grid.Column="0">Test</TextBlock> 19 <TextBlock Grid.Row="1" Grid.Column="1">Test</TextBlock> 20 <TextBlock Grid.Row="2" Grid.Column="0">Test</TextBlock> 21 <TextBlock Grid.Row="2" Grid.Column="1">Test</TextBlock> 22 <TextBlock Grid.Row="3" Grid.Column="0">Test</TextBlock> 23 <TextBlock Grid.Row="3" Grid.Column="1">Test</TextBlock> 24 </Grid>--> 25 <!--<StackPanel Orientation="Horizontal"> 26 <Label>Test</Label> 27 <TextBlock>Test</TextBlock> 28 <TextBlock>Test</TextBlock> 29 <TextBlock>Test</TextBlock> 30 <TextBlock>Test</TextBlock> 31 <TextBlock>Test</TextBlock> 32 <TextBlock>Test</TextBlock> 33 <TextBlock>Test</TextBlock> 34 </StackPanel>--> 35 <Canvas> 36 <Label Canvas.Left="10" Canvas.Top="5">Test</Label> 37 <TextBlock Canvas.Right="100" Canvas.Top="15">Test</TextBlock> 38 <TextBlock Canvas.Right="90" Canvas.Top="25">Test</TextBlock> 39 <TextBlock Canvas.Right="80" Canvas.Top="35">Test</TextBlock> 40 <TextBlock Canvas.Right="70" Canvas.Top="45">Test</TextBlock> 41 <TextBlock Canvas.Right="60" Canvas.Top="55">Test</TextBlock> 42 <TextBlock Canvas.Right="50" Canvas.Top="65">Test</TextBlock> 43 <TextBlock Canvas.Right="40" Canvas.Top="75">Test</TextBlock> 44 </Canvas> 45 </Window>
截圖,如圖4,5,6:
圖4 Grid
圖5 Canvas
圖6 StackPanel
結論:
布局過程的復雜性直接取決於使用的 Panel 派生元素的布局行為。 例如,Grid 或 StackPanel 控件提供的功能比 Canvas 控件多很多。 功能大大提高的代價是性能成本也大大提高。 但是,如果不需要 Grid 控件提供的功能,則應使用成本較低的布局控件,如 Canvas 或自定義面板。
參考資料:
http://msdn.microsoft.com/zh-cn/library/bb613542.aspx
http://msdn.microsoft.com/zh-cn/library/ms745058.aspx#LayoutSystem_Measure_Arrange
前面查了下,附上Framework源碼下載地址:
http://referencesource.microsoft.com/netframework.aspx
如果大家覺得不錯請幫我點下推薦,謝謝~
轉載時,請注明本文來源:www.cnblogs.com/tmywu
作者:Tommywu