說到WPF的界面布局,相信很多朋友都寫過Html代碼。在WPF中,大多數程序都使用類似Web的(flow)流布局。在使用流布局模型時,各種控件可以按特定的要求來排列,在窗口內容發生變化時,比如窗口大小發生變化,界面可以調整自身以及控件的布局。
WPF的布局原則和HTML比較類似,但也有些不同,下面讓我們具體來看看:
WPF布局原則
- 不應顯示設定元素(如控件)的尺寸: 元素應該可以改變尺寸以適應他們的內容,例如當添加更多文本時按鈕應當能夠擴展。很多時候我們在HTML中設置MinWidth 或者 MaxWidth之類屬性去限制控件的尺寸范圍,在WPF也有同樣的應用。
- 不應使用屏幕坐標指定元素的位置:元素應該由他們的容器根據他們的尺寸、順序以及其他特定於具體布局容器的信息進行排列。上面所說的意思其實也和HTML中的元素位置設定很類似,雖然很多時候我們在HTML中也使用坐標進行定位,但實際上這樣的使用情況非常少。
- 布局容器的子元素“共享”可用的空間:如果空間允許,布局容器會根據每個元素的內容盡可能為元素設置更合理的尺寸。它們還會向一個或多個子元素分配多余的空間。這點和HTML中設置各個子元素的寬度和高度很類似,我們可以使用具體的像素(PX)來設置元素尺寸,也可以使用百分比(%)來設置元素所占用的空間,另外子元素為了能填充父元素的空間,可能還對有自動的寬度和高度的調整。
- 可嵌套的布局容器:在WPF中典型的用戶界面使用Grid面板作為開始,Grid面板可以包含其他布局容器。這點也很像Html中的嵌套,我們可以在<Div>中包含再包含<Span>,也可以在<span>中再包含<label>,類似上面的例子的嵌套情況在WPF中也是很常見的。
WPF布局過程
WPF布局包括2個階段:測量(measure)和排列(arrange)。在測量階段,布局容器會遍歷所有子元素,並詢問子元素他們所期望的尺寸,在適合的位置放置子元素。
WPF布局容器
在HTML中我們有多種布局的容器,例如<div>、<table>等等,那么在WPF也存在類似的控件,所有WPF的布局容器都派生自System.Window.Controls.Panel, 下面讓我們來看下Panel類的層次結構:
WPF提供了大量可用於安排布局的繼承自Panel的類,這里我們列舉幾個最基本的類。與所有WPF空間和大多數可視化元素一樣,這些類位於System.Windows.Controls的命名空間中。
名稱 |
說明 |
StackPanel |
在水平或垂直的堆棧中放置元素 |
WrapPanel |
在一系列可換行的行中放置元素 |
DockPanel |
根據容器的整個邊界調整元素 |
Grid |
根據不可見的表格在行和列中排列元素,最常用的容器之一 |
UniformGrid |
在不可見,但是強制所有單元格具有相同尺寸的表格中放置元素 |
Cavas |
使用固定坐標絕對定位元素 |
StackPanel的使用
上面講到了一些關於布局容器的概念和類的說明,現在讓我們依次來看下這些常用的布局容器。
首先我們來看下StackPanel,StackPanel面板是WPF中最簡單的面板之一,該面板簡單地在單行或列中以堆棧形式放置其子元素,默認情況下面板按自上而下的順序排列元素,並且使每個元素的高度適合它的內容,下面讓我們來看一個測試代碼:
<Window x:Class="StackPanelTest.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"> <StackPanel> <Label>A button click</Label> <Button>Button 1</Button> <Button>Button 2</Button> <Button>Button 3</Button> <Button>Button 4</Button> </StackPanel> </Window>
其運行的結果如下圖,所有Button都自上而下排列,按鈕的大小剛好足夠適應他們內部的文本,所有的元素都被拉伸到StackPanel面板的整個寬度。
和HTML的某些控件類似,比如RadioButtonList之類的,我們也可以控制元素的的排列方向,在StackPanel中,我們使用Orientation屬性來控制子元素的排列方向:
<StackPanel Orientation="Horizontal">
布局屬性
StackPanle的布局屬性與HTML的布局容器很類似的,都可以設置對齊方式,外邊距,最大最小寬度、高度等。
1. 對齊方式
首先我們來看下對其方式,在StackPanel中如果是垂直方向的排列,那么VerticalAligment屬性不起作用,因為所有元素的高度都自動地調整為剛好滿足各自需要,但是HorizentalAligment屬性非常重要,它決定了各個元素在行的什么位置。HorizentalAligment有4個值可以選擇:Left, Center, Right 和 Stretch, 相信熟悉Html代碼的朋友來說,前面3個值很容易理解,最后一個值Stretch會將子元素拉伸至整個StackPanel面板的寬度,並且會被設置為默認值,讓我們來看下具體的代碼:
<StackPanel Orientation="Vertical"> <Label HorizontalAlignment="Center">A button click</Label> <Button HorizontalAlignment="Left">Button 1</Button> <Button HorizontalAlignment="Right">Button 2</Button> <Button>Button 3</Button> <Button>Button 4</Button> </StackPanel>
當設置了對其方式后,按鈕的長度和位置都發生了變化,如下圖:
我們看到Button1和Button2設置了對其方式后,他們的位置和按鈕的寬度都發生了變化,這些實際上和HTML中元素的對其方式都很類似的,需要注意的就是Stretch對齊方式對拉伸子元素的寬度為整個StackPanel的寬度。
2. 邊距
在我們平時的布局中,一般不會讓相鄰元素靠得太近,所以在Html中,我們一般會加入Margin這樣的CSS樣式來控制元素的邊距。在WPF中,也有類似的情況,我們可以設置Margin屬性來調整元素的邊距,代碼實例如下:
<Button Margin="5,10,5,4">Button 4</Button>
上面的4個值以逗號分隔,這也和CSS中的設置一樣,分別為上,右,下,左。下圖為設置了Margin的子元素,相鄰的2個子元素之間的距離,為他們各自Margin 之和,代碼如下:
<StackPanel Orientation="Vertical"> <Label HorizontalAlignment="Center">A button click</Label> <Button HorizontalAlignment="Left">Button 1</Button> <Button HorizontalAlignment="Right">Button 2</Button> <Button Margin="30">Button 3</Button> <Button Margin="40">Button 4</Button> </StackPanel>
運行結果如下圖:
我們可以在XAML中設置Margin,也可以在C#代碼中聲明,在代碼中我們使用Thickness結構來設置邊距:
btnShow.Margin = new Thickness(5,3,2,1);
3.最大尺寸、最小尺寸
每個元素都提供Width和Height屬性,用於顯示的指定元素的大小,但有時候子元素的大小超過了父容器的大小時,我們就應當將子元素限制在正確的范圍內,這個時候我們可以用MaxWidth和MaxWidth來進行設置,讓我們來看下示例代碼:
<Button MaxWidth="200" MaxHeight="100" Margin="40">Button 4</Button>
運行結果如下圖:
從上圖我們可以看到,Button4的默認的對齊方式為Stretch,Button4的寬度本來被拉伸至整個StackPanel的寬度,由於我們設置了MaxWidth,最后Button4實際的寬度被設置為200,這樣子就達到了我們要調整合適寬度的目的。
上面就為我們今天說到的第一個布局控件(StackPanel),后續還會為大家梳理其他的布局控件。
本人最近開始學習WPF以及DevExpress,藉此提升自己C/S架構編程的能力。在學習過程會有一些心得體會,於是便會寫一些博客來記錄這些想法,有興趣的朋友可以和我一起交流學習。那么就讓我們從這里開始WPF與DevExpress的旅程吧!
QQ群: 32745894,歡迎大家加入討論!