內容控件不只包括基本控件,如標籤、按鈕以及工具提示;它們還包含特殊容器,這些容器可用於構造用戶界面中比較大的部分區域。api
首先介紹ScrollViewer控件,該控件直接繼承自ContentControl類,提供了虛擬界面,容許用戶圍繞更大的元素滾動。與全部內容控件同樣,ScrollViewer只能包含單個元素,雖然如此,你仍可在內部放置佈局容器來保存本身須要的任意類型的元素。網絡
此後將分析附加繼承層中的另外三個控件:GroupBox、TabItem以及Expander。全部這些控件都繼承自HeaderedContentControl類,HeaderedContentControl又繼承自ContentControl類。HeaderedContentControl類的做用十分簡單,它表示包含單一元素內容(存儲在Content屬性中)和單一元素標題(存儲在Header屬性中)的容器。正是因爲添加了標題,才使HeaderedContentControl與前面章節介紹的內容控件區別開來。重申一次,可以使用標題和或內容的佈局容器,將內容封裝在HeaderedContentControl中。app
1、ScrollVieweride
若是但願讓大量內容適應有限的空間,滾動是重要特性之一。在WPF中爲了得到滾動支持,須要在ScrollViewer控件中封裝但願滾動的內容。工具
儘管ScrollViewer控件能夠包含任何內容,但一般用來封裝佈局容器。以下示例中,使用Grid元素建立三列,用於顯示文本、文本框和按鈕。爲使這個Grid面板可以滾動,只需將Grid面板封裝到ScrollViewer控件中,以下面的標記所示:佈局
<ScrollViewer Name="scroller"> <Grid Margin="0,10,0,0" Focusable="False"> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"></ColumnDefinition> <ColumnDefinition Width="*" MinWidth="50" MaxWidth="800"></ColumnDefinition> <ColumnDefinition Width="Auto"></ColumnDefinition> </Grid.ColumnDefinitions> <Label Grid.Row="0" Grid.Column="0" Margin="3" VerticalAlignment="Center">Home:</Label> <TextBox Grid.Row="0" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="0" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="1" Grid.Column="0" Margin="3" VerticalAlignment="Center">Network:</Label> <TextBox Grid.Row="1" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="1" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="2" Grid.Column="0" Margin="3" VerticalAlignment="Center">Web:</Label> <TextBox Grid.Row="2" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="2" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="3" Grid.Column="0" Margin="3" VerticalAlignment="Center">Secondary:</Label> <TextBox Grid.Row="3" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="3" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="4" Grid.Column="0" Margin="3" VerticalAlignment="Center">Home:</Label> <TextBox Grid.Row="4" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="4" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="5" Grid.Column="0" Margin="3" VerticalAlignment="Center">Network:</Label> <TextBox Grid.Row="5" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="5" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="6" Grid.Column="0" Margin="3" VerticalAlignment="Center">Web:</Label> <TextBox Grid.Row="6" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="6" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="7" Grid.Column="0" Margin="3" VerticalAlignment="Center">Secondary:</Label> <TextBox Grid.Row="7" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="7" Grid.Column="2" Margin="3" Padding="2">Browse</Button> </Grid> </ScrollViewer>
最終效果以下圖所示:ui
在該例中,若是改變窗口的尺寸以使窗口足以容納全部內容,將會禁用滾動條。但仍會顯示滾動條,可經過設置VerticalScrollBarVisibility屬性來控制這一行爲,該屬性使用ScrollBarVisibility枚舉值。默認值 Visible確保老是提供垂直滾動條。若是但願當須要時顯示滾動條而當不須要時不顯示,可將該屬性設置爲Auto。若是根本就不但願顯示滾動條,可將該屬性設置爲Disable。編碼
ScrollViewer控件也支持水平滾動功能。但默認狀況下,HorizontalScrollBarVisibility屬性設置爲Hidden。爲了使用水平滾動功能,須要將該屬性改成Visible或Auto。spa
一、經過代碼進行滾動3d
爲滾動上圖中顯示的窗口,可以使用鼠標單擊滾動條,將鼠標移到網絡上並使用鼠標滾輪進行滾動,可以使用Tab鍵查看控件,或單擊網格控件的空白處並使用向上或向下的方向鍵進行滾動。若是這些還不夠靈活,還可以使用ScrollViewer類提供的方法,經過代碼來滾動內容:
如今建立一個簡單的示例,代碼以下所示:
<Window x:Class="Controls.ScrollableTextBoxColumn" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="ScrollableTextBoxColumn" Height="230.075" Width="300"> <DockPanel> <Border DockPanel.Dock="Top" BorderBrush="SteelBlue" BorderThickness="2"> <StackPanel Margin="5" Orientation="Horizontal"> <Button Padding="3" Click="LineUp">Line Up</Button> <Button Padding="3" Click="LineDown">Line Down</Button> <Button Padding="3" Click="PageUp">Page Up</Button> <Button Padding="3" Click="PageDown">Page Down</Button> </StackPanel> </Border> <ScrollViewer Name="scroller"> <Grid Margin="0,10,0,0" Focusable="False"> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"></ColumnDefinition> <ColumnDefinition Width="*" MinWidth="50" MaxWidth="800"></ColumnDefinition> <ColumnDefinition Width="Auto"></ColumnDefinition> </Grid.ColumnDefinitions> <Label Grid.Row="0" Grid.Column="0" Margin="3" VerticalAlignment="Center">Home:</Label> <TextBox Grid.Row="0" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="0" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="1" Grid.Column="0" Margin="3" VerticalAlignment="Center">Network:</Label> <TextBox Grid.Row="1" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="1" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="2" Grid.Column="0" Margin="3" VerticalAlignment="Center">Web:</Label> <TextBox Grid.Row="2" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="2" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="3" Grid.Column="0" Margin="3" VerticalAlignment="Center">Secondary:</Label> <TextBox Grid.Row="3" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="3" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="4" Grid.Column="0" Margin="3" VerticalAlignment="Center">Home:</Label> <TextBox Grid.Row="4" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="4" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="5" Grid.Column="0" Margin="3" VerticalAlignment="Center">Network:</Label> <TextBox Grid.Row="5" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="5" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="6" Grid.Column="0" Margin="3" VerticalAlignment="Center">Web:</Label> <TextBox Grid.Row="6" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="6" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="7" Grid.Column="0" Margin="3" VerticalAlignment="Center">Secondary:</Label> <TextBox Grid.Row="7" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="7" Grid.Column="2" Margin="3" Padding="2">Browse</Button> </Grid> </ScrollViewer> </DockPanel> </Window>
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; namespace Controls { /// <summary> /// ScrollableTextBoxColumn.xaml 的交互邏輯 /// </summary> public partial class ScrollableTextBoxColumn : Window { public ScrollableTextBoxColumn() { InitializeComponent(); } private void LineUp(object sender, RoutedEventArgs e) { scroller.LineUp(); } private void LineDown(object sender, RoutedEventArgs e) { scroller.LineDown(); } private void PageUp(object sender, RoutedEventArgs e) { scroller.PageUp(); } private void PageDown(object sender, RoutedEventArgs e) { scroller.PageDown(); } } }
最終效果以下所示:
二、自定義滾動條
ScrollViewer控件內置的滾動功能是頗有用的。該功能容許緩慢滾動任何內容,從複雜的矢量圖形乃至元素網格。不過,ScrollViewer控件最奇特的特徵是容許其包含的內容參與滾動過程。下面是工做原理:
(1)在ScrollViewer控件中放置能滾動的元素,能夠是實現了IScrollInfo接口的任意元素。
(2)經過將ScrollViewer.CanContentScroll屬性設置爲true,告訴ScrollViewer控件其內容知道如何進行滾動。
(3)當和ScrollViewer控件進行交互時(經過使用滾動條、鼠標輪和滾動方法等),ScrollViewer控件經過IScrollInfo接口來調用元素的恰當方法。元素接着執行它本身的自定義滾動功能。
IScrollInfo接口定義了一套方法,這套方法響應不一樣的滾動動做。例如,它包含了ScrollViewer控件提供的許多滾動方法,如LineUp()、LineDown()、PageUp()以及PageDown()。它還定義了一些處理鼠標滾輪的方法。
實現了IScrollInfo接口的元素極少,其中一個元素是StackPanel面板容器。StackPanel類對IScrollInfo接口的實現使用邏輯滾動,從元素滾動到元素,而不是逐行滾動。
若是在ScrollViewer控件中放置StackPanel面板,並且不設置CanContentScroll,將獲得普通的滾動行爲。一次可向上或向下滾動幾個像素。但若是將CanContentScroll屬性設置爲true,那麼每次單擊時會滾動到下一個元素的開頭:
<ScrollViewer CanContentScroll="True"> <StackPanel> <Button Height="100">1</Button> <Button Height="100">2</Button> <Button Height="100">3</Button> <Button Height="100">4</Button> </StackPanel> </ScrollViewer>
StackPanel面板的邏輯滾動系統對應用程序可能有用也可能沒用。可是,若是要建立具備特殊滾動行爲的自定義面板,它是必不可少的。
2、GroupBox
GroupBox是這三個繼承自HeaderedContentControl類的控件中最簡單的一個。它顯示爲具備圓角和標題的方框。下面是一個示例,下過以下圖所示:
<Window x:Class="Controls.GroupBoxDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="GroupBoxDemo" Height="300" Width="300"> <Grid> <GroupBox Header="A GroupBox Test" Padding="5" Margin="5" VerticalAlignment="Top"> <StackPanel> <RadioButton Margin="3">One</RadioButton> <RadioButton Margin="3">Two</RadioButton> <RadioButton Margin="3">Three</RadioButton> <Button Margin="3">Save</Button> </StackPanel> </GroupBox> </Grid> </Window>
3、TabItem
TabItem表示TabControl控件中的一頁。TabItem類添加的惟一有意義的屬性是IsSelected,該屬性只是選項卡(tab)當前是否顯示在TabControl控件中。下面是建立簡單示例:
<Window x:Class="Controls.TabItemDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="TabItemDemo" Height="300" Width="300"> <TabControl Margin="5"> <TabItem Header="Tab One"> <StackPanel Margin="5"> <CheckBox Margin="3">Setting One</CheckBox> <CheckBox Margin="3">Setting Two</CheckBox> <CheckBox Margin="3">Setting Three</CheckBox> </StackPanel> </TabItem> <TabItem Header="Tab Two"> <StackPanel Margin="5"> <CheckBox Margin="3">Setted One</CheckBox> <CheckBox Margin="3">Setted Two</CheckBox> <CheckBox Margin="3">Setted Three</CheckBox> </StackPanel> </TabItem> </TabControl> </Window>
可使用TabStripPlacement屬性,使各個選項卡在選項卡控件的側邊顯示,而不是在正常頂部位置顯示。
與Content屬性意義,Header屬性也能夠接受任何類型的對象。繼承自UIElement的類經過渲染來顯示,對於內斂文本以及其餘全部對象則使用ToString()方法。這意味着能夠建立組合框或選項卡,在他們的標題中包含圖形內容或任意元素。下面是一個示例:
<Window x:Class="Controls.GraphicalTabTitles" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="GraphicalTabTitles" Height="300" Width="300"> <TabControl Margin="5" > <TabItem> <TabItem.Header> <StackPanel> <TextBlock Margin="3">Image and Text Tab Title</TextBlock> <Image Source="happyface.jpg" Stretch="None"></Image> </StackPanel> </TabItem.Header> <StackPanel Margin="5"> <CheckBox Margin="3">Setting One</CheckBox> <CheckBox Margin="3">Setting Two</CheckBox> <CheckBox Margin="3">Setting Three</CheckBox> </StackPanel> </TabItem> <TabItem Header="Tab Two"> <StackPanel Margin="5"> <CheckBox Margin="3">Setted One</CheckBox> <CheckBox Margin="3">Setted Two</CheckBox> <CheckBox Margin="3">Setted Three</CheckBox> </StackPanel> </TabItem> </TabControl> </Window>
4、Expander
最奇特的具備標題的內容控件是Expander控件。它封裝了一塊內容,經過單擊小箭頭按鈕能夠顯示或隱藏所包含的內容。
使用Expander控件是十分簡單的——只需在該控件內部包裝但願使其可以摺疊的內容。一般,每一個Expander控件開始時都是摺疊的,但可在標記中(或代碼中)經過設置IsExpanded屬性來改變這種行爲。下面是一個簡單Expander示例:
<Window x:Class="Controls.ExpandableContent" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="ExpandableContent" Height="300" Width="300" SizeToContent="Height"> <StackPanel> <Expander Margin="5" Padding="5" Header="Region One" BorderThickness="1" BorderBrush="Black"> <Button Padding="3">Hidden Button One</Button> </Expander> <Expander Margin="5" Padding="5" Header="Region Two" BorderThickness="1" BorderBrush="Black"> <TextBlock TextWrapping="Wrap"> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam mi sapien, viverra et, lacinia varius, ullamcorper sed, sapien. Proin rutrum arcu vitae tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque libero dui, eleifend faucibus, auctor at, aliquet a, nulla. Nunc eros. Phasellus mauris nisi, eleifend nec, adipiscing nec, luctus nec, lacus. Aliquam justo metus, vestibulum non, accumsan id, hendrerit at, nibh. Praesent accumsan urna quis tortor. Proin erat libero, facilisis nec, rhoncus ut, malesuada ut, ipsum. Donec id nibh. </TextBlock> </Expander> <Expander Margin="5" Padding="5" Header="Region Three" IsExpanded="True" BorderThickness="1" BorderBrush="Black"> <Button Padding="3">Hidden Button Two</Button> </Expander> </StackPanel> </Window>
還能夠選擇擴展器的方向。上圖使用的是標準值(Down),但也可將ExpandDirection樹上設置爲Up、Left或Right。當摺疊Expander時,箭頭始終指向將要展開的方向。
當使用不一樣的ExpandDirection值,狀況就比較有趣了,由於對用戶界面其餘部分的影響取決於容器的類型。有些容器(如WrapPanel面板)只要擠壓其餘元素使其離開原來的位置。其餘容器,如Grid面板,能夠選擇按比例或自動改變大小。下面有一個示例使用不一樣展開程度,該示例有一個具備4個單元格的網格。每一個單元格中都包含一個具備不一樣展開方向的擴展器。例按比例改變其大小,從而強制Expander控件中的文本進行換行(自動改變尺寸的列回簡單地被拉伸以適應文本,使它比窗口還大)。行被設置爲自動改變尺寸,因此會擴展以容納附加的內容。
示例代碼以下所示:
<Window x:Class="Controls.MultiDirectionExpanders" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MultiDirectionExpanders" Height="327.2" Width="328.8"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition ></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <Expander Margin="5" Padding="5" Header="Region One" BorderThickness="1" BorderBrush="Black"> <TextBlock TextWrapping="Wrap"> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam mi sapien, viverra et, lacinia varius, ullamcorper sed, sapien. </TextBlock> </Expander> <Expander Grid.Column="1" Margin="5" Padding="5" Header="Region Two" ExpandDirection="Right" BorderThickness="1" BorderBrush="Black"> <TextBlock TextWrapping="Wrap"> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam mi sapien, viverra et, lacinia varius, ullamcorper sed, sapien. </TextBlock> </Expander> <Expander Grid.Row="1" Margin="5" Padding="5" Header="Region Three" ExpandDirection="Up" BorderThickness="1" BorderBrush="Black"> <TextBlock TextWrapping="Wrap"> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam mi sapien, viverra et, lacinia varius, ullamcorper sed, sapien. </TextBlock> </Expander> <Expander Grid.Row="1" Grid.Column="1" Margin="5" Padding="5" Header="Region Three" ExpandDirection="Left" BorderThickness="1" BorderBrush="Black"> <TextBlock TextWrapping="Wrap"> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam mi sapien, viverra et, lacinia varius, ullamcorper sed, sapien. </TextBlock> </Expander> </Grid> </Window>
在WPF程序中使用Expander控件是很是合適的,由於WPF鼓勵使用流式佈局模型,從而能夠很方便地處理會大幅增大或縮小的內容區域。
若是要使其餘控件與Expander同步,可處理Expanded和Collapsed事件。這些事件的名稱並未代表其含義,這些事件正好在顯示或隱藏內容前觸發。這兩個事件爲實現延遲加載提供一種有用的方法。例如,若是建立Expander控件中的內容很是耗時,可能會直到要顯示時才檢索這些內容。或者可能但願在顯示以前更新內容。不管哪一種狀況,均可以經過響應Expanded事件來執行相應的工做。
一般,當展開Expander時,它會增大以適應所包含的內容。當展開全部內容後,若是窗口不足以顯示全部內容,這可能會帶來問題。下面是處理該問題的集中策略:
對於大多數狀況,這些技術都是很是簡單的。惟一須要進一步說明的是如何組合使用Expander控件和ScrollViewer控件,爲讓這個方法湊效,須要贏編碼ScrollViewer控件的尺寸。不然,ScrollViewer控件會進行擴展以適應它包含的內容。下面是一個示例:
<Window x:Class="Controls.ExpandableScrollableContent" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="ExpandableScrollableContent" Height="300" Width="300"> <StackPanel> <Expander Margin="5" Padding="5" Header="Region One"> </Expander> <Expander Margin="5" Padding="5" Header="Region Two" > <ScrollViewer Height="50" > <TextBlock TextWrapping="Wrap"> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam mi sapien, viverra et, lacinia varius, ullamcorper sed, sapien. Proin rutrum arcu vitae tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque libero dui, eleifend faucibus, auctor at, aliquet a, nulla. Nunc eros. Phasellus mauris nisi, eleifend nec, adipiscing nec, luctus nec, lacus. Aliquam justo metus, vestibulum non, accumsan id, hendrerit at, nibh. Praesent accumsan urna quis tortor. Proin erat libero, facilisis nec, rhoncus ut, malesuada ut, ipsum. Donec id nibh. </TextBlock> </ScrollViewer> </Expander> <Expander Margin="5" Padding="5" Header="Region Three" IsExpanded="True"> <Button Padding="3">Hidden Button Two</Button> </Expander> </StackPanel> </Window>
若是有一個系統,能讓Expander控件根據窗口的可用空間,設置內容區域的尺寸,那將是很是好的。但這會明顯增長複雜度(例如,當Expander控件展開時,若是在多個區域共享空間)。Grid佈局容器看起來像是潛在的解決方案,但它不能和Expander控件很好地集成。若是嘗試這樣的作的話,當摺疊Expander控件時,可能致使很是奇怪的行爲,不能正確地更新網格的行高。