WPF之旅(三)- 布局之StackPanel


說到WPF的界面布局,相信很多朋友都寫過Html代碼。在WPF中,大多數程序都使用類似Web的(flow)流布局。在使用流布局模型時,各種控件可以按特定的要求來排列,在窗口內容發生變化時,比如窗口大小發生變化,界面可以調整自身以及控件的布局。

 

WPF的布局原則和HTML比較類似,但也有些不同,下面讓我們具體來看看:

WPF布局原則

  1. 不應顯示設定元素(如控件)的尺寸: 元素應該可以改變尺寸以適應他們的內容,例如當添加更多文本時按鈕應當能夠擴展。很多時候我們在HTML中設置MinWidth 或者 MaxWidth之類屬性去限制控件的尺寸范圍,在WPF也有同樣的應用。
  2. 不應使用屏幕坐標指定元素的位置:元素應該由他們的容器根據他們的尺寸、順序以及其他特定於具體布局容器的信息進行排列。上面所說的意思其實也和HTML中的元素位置設定很類似,雖然很多時候我們在HTML中也使用坐標進行定位,但實際上這樣的使用情況非常少。
  3. 布局容器的子元素“共享”可用的空間:如果空間允許,布局容器會根據每個元素的內容盡可能為元素設置更合理的尺寸。它們還會向一個或多個子元素分配多余的空間。這點和HTML中設置各個子元素的寬度和高度很類似,我們可以使用具體的像素(PX)來設置元素尺寸,也可以使用百分比(%)來設置元素所占用的空間,另外子元素為了能填充父元素的空間,可能還對有自動的寬度和高度的調整。
  4. 可嵌套的布局容器:在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,歡迎大家加入討論!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM