顯然,只使用StackPanel面板還不餓能幫助用戶創建出實用的用戶界面。要設計出最終使用的用戶界面,StackPanel面板還需要與其他更強大的布局容器協作。只有這樣才能組裝成完整的窗口。
最復雜的布局容器是Grid面板,后面幾章會進行介紹。在介紹Grid面板之前,有必要首先看一下WrapPanel和DockPanel面板,它們是WPF提供的兩個更簡單的布局容器。這兩個布局容器通過不同的布局行為對StackPanel面板進行補充。
一、WrapPanel面板
WrapPanel面板在可能的空間中,以一次一行或一列的方式布置控件。默認情況下,WrapPanel.Orientation的屬性設置為Horizontal;控件從左向右進行排列,再在下一行中排列。但可將WrapPenel.Orientation的屬性設置為Vertical,從而在多個列中放置元素。
下面的示例中定義了一系列具有不同對齊方式的按鈕,並將這些按鈕放到一個WrapPanel面板中:
<Window x:Class="WrapPanelLayout.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <WrapPanel Margin="5"> <Button VerticalAlignment="Top">Top Button</Button> <Button MinHeight="60">Tall Button</Button> <Button VerticalAlignment="Bottom">Bottom Button</Button> <Button>Stretch Button</Button> <Button VerticalAlignment="Center">Center Button</Button> </WrapPanel> </Window>
下圖顯示了如何對這些阿牛進行換行以適應WrapPanel面板的當前尺寸(WrapPanel面板的當前尺寸是由包含它的窗口的尺寸決定的)。正如這個示例所演示的,WrapPanel面板水平地創建了一系列假想的行,每一行的高度都被設置所包含元素中最高元素的高度。其他控件可能被拉伸以適應這一高度,或根據VerticalAlignment屬性的設置進行對齊。
當窗口大小進行變化時,有幾個按鈕被擠到第二行中。因為第二行沒有包含特別高的按鈕,所以第二行的高度保持最小按鈕的高度。因此,在該行中不必關系各按鈕的VerticalAlignment屬性的設置。
WrapPanel面板是唯一一個不能通過靈活使用Grid面板代替的面板。
二、DockPanel面板
DockPanel面吧是更有趣的布局選項。它沿着一條外邊緣來拉伸所包含的控件。理解該面板最簡便的方式是,考慮一下位於許多Windows應用程序窗口頂部的工具欄,這些工具欄停靠到窗口頂部。與StackPanel面板類似,被停靠的元素選擇它們的布局的一方面。例如,如果將一個阿牛停靠在DockPanel面板頂部,該按鈕被拉伸至DockPanel面板的整個寬度,但根據內容和MinHeight屬性為其設置所需的高度。而如果將一個按鈕停靠到容器左邊,該按鈕的高度將被拉伸以適應容器的高度,而其寬度可以根據需要自由添加。
這里很明顯的問題是:子元素如何選擇停靠的邊?答案是通過Dock附加屬性,可將該屬性設置為Left、Right、Top或Bottom。放在DockPanel面板中的每個元素都會自動捕獲該屬性。
下面的示例在DockPanel面板的每條邊上都停靠一個按鈕:
<Window x:Class="DockPanelLayout.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <DockPanel LastChildFill="True"> <Button DockPanel.Dock="Top">Top Button</Button> <Button DockPanel.Dock="Bottom">Bottom Button</Button> <Button DockPanel.Dock="Left">Left Button</Button> <Button DockPanel.Dock="Right">Right Button</Button> <Button>Content Button</Button> </DockPanel> </Window>
該例還將DockPanel面板的LastChildFill屬性設置為True,該設置告訴DockPanel面板使最后一個元素占滿剩余空間。效果如下圖所示:
顯然,當停靠控件時,停靠順序很重要。在這個示例中,頂部和底部按鈕充滿了DockPanel面板的整個邊緣,這是因為這兩個按鈕首先停靠。接着停靠左邊和右邊的按鈕時,這兩個按鈕將位於頂部按鈕和底部按鈕之間。如果改變這一順序,那么左邊和右邊的按鈕將充滿整個面板的邊緣,二頂部和底部的按鈕則變窄一些,因為它們將在左邊和右邊的兩個按鈕之間進行停靠。
可將多個元素停靠到同一邊緣。這種情況下,元素按標記中聲明的順序停靠到邊緣。而且,如果不喜歡空間分割或拉伸行為,可修改Margin屬性、HorizontalAlignment屬性以及VerticalAlignment屬性,就像使用StackPanel面板進行布局時所介紹的那樣。下面對前面示例進行修改:
<Window x:Class="DockPanelLayout.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <DockPanel LastChildFill="True"> <Button DockPanel.Dock="Top">A Stretched Top Button</Button> <Button DockPanel.Dock="Top" HorizontalAlignment="Center">A Centered Top Button</Button> <Button DockPanel.Dock="Top" HorizontalAlignment="Left">A Left-Aligned Top Button</Button> <Button DockPanel.Dock="Bottom">Bottom Button</Button> <Button DockPanel.Dock="Left">Left Button</Button> <Button DockPanel.Dock="Right">Right Button</Button> <Button>Content Button</Button> </DockPanel> </Window>
修改后效果圖如下所示:
三、嵌套布局
很少單獨使用StackPanel、WrapPanel和DockPanel面板。相反,它們通常用來設置一部分用戶界面的布局。例如,可使用DockPanel面板在窗口的合適區域放置不同的StackPanel和WrapPanel面板容器。
例如,假設希望創建一個標准對話框,在其右下角具有兩個按鈕,並且在窗口的剩余部分是一塊較大的內容區域。在WPF中可采用幾種方法完成這一布局,但最簡答的方法如下:
(1)創建水平StackPanel面板,用於將按鈕放置在一起。
(2)在DockPanel面板中方式StackPanel面板,將其停靠到窗口底部。
(3)將DockPanel.LastChildFill屬性設置為true,以使用窗口剩余的部分填充其它內容。
(4)設置邊距屬性,提供一定的空間。
下面是最終的標記:
<Window x:Class="DockPanelLayout.CombineLayout" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="CombineLayout" Height="300" Width="300"> <DockPanel LastChildFill="True"> <StackPanel DockPanel.Dock="Bottom" HorizontalAlignment="Right" Orientation="Horizontal"> <Button Margin="10,10,2,10" Padding="3">OK</Button> <Button Margin="2,10,10,10">Cancle</Button> </StackPanel> <TextBox DockPanel.Dock="Top" Margin="10">This is test.</TextBox> </DockPanel> </Window>
最終效果圖如下所示: