理解布局
wpf布局原则
wpf窗体只能包含单个元素。为了在窗体上放置多个元素创建符合界面需求的用户界面,就需要使用容器控件添加其他元素。可以理解为wpf的布局是由你使用的容器元素决定的。
布局过程
布局包含两个过程:测量阶段和排列阶段,测量阶段容器遍历所有子元素,询问期望尺寸。排列阶段在合适的位置放置子元素。不是所有子元素的尺寸都适应容器,超出部分或被裁剪掉。
布局容器
所有容器都是System.Windows.Controls.Panel。都包含三个共有属性:
Background:背景着色画刷。
Children:存储子集控件集合
IsItemsHost:该属性值为布尔值。
核心布局面板:
- StackPanel:在水平或垂直中放置元素。
- WrapPanel:在一系列可换行中放置元素。
- DockPanel:根据容器的整个边缘调整元素。
- Grid:表格排列元素。
- UnifromGrid:强制所有单元格相同尺寸中放置元素。
- Canvas:固定坐标决定定位布局填充元素。
StackPanel布局简单案例
<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>
界面效果:
默认情况下,StackPanel面板是按照至上而下的顺序排列元素,使得每个元素的高度适合它的内容。通过设置Orientation="Horizontal"可以使其水平排列元素。
布局属性
- HorizontalAligument:当水平空间有空余时用来决定元素停靠位置,可选Center,left,right,Strech
- VerticalAlignment:同理当垂直空间有空余时用来决定元素停靠位置,可选Center,left,right,Strech
- Margin:用来定义元素间距
- MinWidth和MinHeight及MaxWidth和MaxHeight:定于最大最小宽高
- Width和Height:用来定义元素宽高
Border控件
它不是布局元素,是常用的布局元素。它的作用是用来添加边框效果。
使用案例:
<Grid>
<Border BorderBrush="BlueViolet"
BorderThickness="10"
Margin="20">
<StackPanel>
<Button>Button1</Button>
<Button>Button2</Button>
</StackPanel>
</Border>
</Grid>
效果如下:
WrapPanel布局案例
在可能的空间中,以一次一行或一列的方式布局。默认是控件从左到右进行排列,可通过WrapPanel.Orientation属性设置改变。
<WrapPanel>
<Button>Test button 1</Button>
<Button>Test button 2</Button>
<Button>Test button 3</Button>
<Button Height="40">Test button 4</Button>
<Button>Test button 5</Button>
<Button>Test button 6</Button>
</WrapPanel>
效果如下:
改变排列属性:
<WrapPanel Orientation="Vertical">
<Button>Test button 1</Button>
<Button>Test button 2</Button>
<Button>Test button 3</Button>
<Button Width="140">Test button 4</Button>
<Button>Test button 5</Button>
<Button>Test button 6</Button>
</WrapPanel>
效果如下:
DockPanel布局案例
该控件非常有意思,他会沿着一条外边缘来拉伸包含的控件。指定停靠边的控件,会根据定义的顺序占领边角,所有控件绝不会交叠。
默认情况下,后添加的元素只能使用剩余空间,无论对DockPanel的最后一个子元素设置任何停靠值,该子元素都将始终填满剩余的空间。
简单示例:
<DockPanel>
<Button DockPanel.Dock="Left" Content="ButtonLeft"></Button>
<Button DockPanel.Dock="Top" Content="ButtonTop"></Button>
<Button DockPanel.Dock="Right" Content="ButtonRight"></Button>
<Button DockPanel.Dock="Bottom" Content="ButtonBottom"></Button>
<Button Content="ButtonTop"></Button>
</DockPanel>
效果如下:
Grid布局案例
最常用的布局,不可见表格形式行列的形式布局。可是通过<Grid.RowDefinitions><Grid.ColumnDefinitions>设置多列多行表格布局。常用属性还有RowSpan和ColumnSpan可实现跨行跨列填充数据。
简单案例:
<Grid ShowGridLines="True">
<!--定义行,3行-->
<Grid.RowDefinitions>
<!--自动行高-->
<RowDefinition Height="Auto"></RowDefinition>
<!--按比例行高-->
<RowDefinition Height="*"></RowDefinition>
<!--固定行高-->
<RowDefinition Height="50"></RowDefinition>
</Grid.RowDefinitions>
<!--定义列,2列-->
<Grid.ColumnDefinitions>
<!--按比例列宽-->
<ColumnDefinition Width="*"></ColumnDefinition>
<!--固定列宽-->
<ColumnDefinition Width="200"></ColumnDefinition>
</Grid.ColumnDefinitions>
<!--定义元素,并指定单元格-->
<TextBlock Grid.Row="0" Grid.Column="0" >第一行第一列</TextBlock>
<TextBlock Grid.Row="1" Grid.Column="0" >第二行第一列</TextBlock>
<TextBlock Grid.Row="2" Grid.Column="0" >第三行第一列</TextBlock>
<Button Grid.Row="0" Grid.Column="1">第一行第二列</Button>
<Button Grid.Row="1" Grid.Column="1">第二行第二列</Button>
<Button Grid.Row="2" Grid.Column="1">第三行第二列</Button>
</Grid>
效果如下:
分割窗口:
通过GridSplitter实现窗口分割,拖动分割线实现窗口大小变动。
简单案例:
<Grid Name="gridMain">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30*"/>
<ColumnDefinition Width="70*"/>
</Grid.ColumnDefinitions>
<Label Background="LightBlue" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Grid.Row="0" Grid.Column="0">Column1</Label>
<GridSplitter Width="5"></GridSplitter>
<Label Background="LightGreen" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Grid.Row="0" Grid.Column="1">Column2</Label>
</Grid>
效果如下:
Canvas布局案例
允许使用精确坐标放置元素,多个元素叠加呈现可以使用Canvas.ZIndex属性定义呈现顺序。需要定义Canvas.Top和Canvas.Left属性值,不然多个元素时会统一在左上角程序。
简单案例:
<Canvas>
<Rectangle Canvas.ZIndex="3" Width="100" Height="100" Canvas.Top="100" Canvas.Left="100" Fill="blue"/>
<Rectangle Canvas.ZIndex="1" Width="100" Height="100" Canvas.Top="150" Canvas.Left="150" Fill="yellow"/>
<Rectangle Canvas.ZIndex="2" Width="100" Height="100" Canvas.Top="200" Canvas.Left="200" Fill="green"/>
<Rectangle Canvas.ZIndex="1" Width="100" Height="100" Canvas.Top="300" Canvas.Left="200" Fill="green"/>
<Rectangle Canvas.ZIndex="3" Width="100" Height="100" Canvas.Top="350" Canvas.Left="150" Fill="yellow"/>
<Rectangle Canvas.ZIndex="2" Width="100" Height="100" Canvas.Top="400" Canvas.Left="100" Fill="blue"/>
</Canvas>
效果如下: