WPF Panel的效能分析

來源:互聯網
上載者:User

  大家知道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

郵箱:tommywu23@126.com

 

 

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.