布局
与传统的WindowsUI界面设计不同的是。WPF更倡导使用布局对界面元素进行管理,而不是使用固定的left、top、width及height这些数字来确定。使用布局可以更有效的适应界面的变化,以创建与显示分辨率和窗口大小无关的并在不同显示器上可以很好进行缩放的用户界面;当窗口内容发生变化时可调整之身;容易地进行语言切换。
为了很好的使用WPF布局系统,所以要遵循以下布局原则:
1. 不应显式设定元素(例如控件)的尺寸。不过可以设置元素的最大最小尺寸来进行限制;
2. 不应使用屏幕坐标指定元素的位置。各种布局容器会自动管理其内部的元素;
3. 布局容器和它们的子元素“共享”可以使用空间。
4. 可以嵌套布局容器。这样对界面进行合适的分解后,通过不同布局元素的嵌套使用可以设计出符合WPF规范的界面;
WPF布局包括两个阶段:测量和排列。在测量阶段容器遍历所有子元素,并查询子元素期望的尺寸;在排列阶段容器在合适位置放置子元素,但若子元素尺寸超过布局容器则会导致截断,所以尽量不要直接限定子元素的Height或Width值,这样容易导致发生截断。
所有的布局容器都派生子System.Windows.Controls.Panel类,该类包含一个Children属性,该属性是System.Windows.Controls.UIElementCollection对象,容器中的所有元素都会添加进Children集合中。WPF中常用的布局容器有以下几种
StackPanel 在水平或垂直堆栈中放置元素
WrapPanel 在一系列可换行的行中放置元素
DockPanel 根据容器的整个边界调整元素
Grid 根据一个不可见的表格在行和列中安排元素
UniformGrid 同Grid当要求表格所有单元格格式一致
Canvas 使用固定坐标定位元素
例如Window和Button这一类的控件都是内容控件,所以将某一布局对象赋予Content就可以在该控件中放置不同的控件。下面简单介绍以上几种控件的使用方式;
1 StackPanel
形如:
<StackPanel>
<Label>A Button Stack</Label>
<Button>Button 1</Button>
<Button>Button 2</Button>
<Button>Button 3</Button>
</StackPanel>
这样的XAML标记将在窗体中创建一个垂直排列的StackPanel,其中含有一个Label和三个Button,而若要改变排列为水平方向,则给StackPanel的Orientation赋予Horizontal
2 WrapPanel
形如:
<WrapPanel>
<Label>A Button Stack</Label>
<Button>Button 1</Button>
<Button>Button 2</Button>
<Button>Button 3</Button>
</WrapPanel>
这样会在一行依次添加Label和Button。当不足以在一行显示时,回自动换行显示。与StackPanel相反,WrapPenal默认Orientation值为Horizontal,若要是控件按列显示,则使Orientation值为Vertical即可。
3 DockPanel
形如:
<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>Remaining Space Button</Button>
</DockPanel>
DockPanel中的元素使用附加属性语法DockPanel.Dock=“Top”指定该元素在DockPanel中的位置。而LastChildFill属性指定最后一个元素是否占满剩余的空间。
4 Grid
1<Grid>
2 <Grid.RowDefinitions>
3 <RowDefinition Height="Auto"/>
4 <RowDefinition Height="*"/>
5 </Grid.RowDefinitions>
6 <Grid.ColumnDefinitions>
7 <ColumnDefinition Width="Auto"/>
8 <ColumnDefinition Width="*"/>
9 <Grid.ColumnDefinitions>
10 <Button Grid.Row="0" Grid.Column="0" Grid.RowSpan="1" Grid.ColumnSpan="1">Button 1</Button>
11 <Button Grid.Row="1" Grid.Column="1" Grid.RowSpan="1" Grid.ColumnSpan="1">Button 1</Button>
12</Grid>
这样的代码定义了一个两行两列的Grid,并在左上角和右下角的Cell中各放置了一个Button对象。在第2行和第6行中定义了一个行的集合和一个列的集合,可在其中添加行定义对象或列定义对象,其中行定义要制定高度,列定义要制定宽度。以行为例,第一个的高度为Auto表示该行的高度会自适应该行内对高度要求最大的元素的高度。而*表示该行的高度会占满第一行之外剩余的空间。而如果在追加一行定义,并且高度为2*,在第一行之外剩余的空间会按比例分配给第二行和第三行。列定义与行定义在这点上相同。
要给Grid中的元素指定位置的时候要使用附加属性语法,明确指定元素的行和列位置,以及该元素的所跨的行数和列数。默认元素会在第一行第一列,RowSpan和ColumnSpan都为1。Grid是最经常用到的布局,使用Grid可以模拟出其他布局,而且使用Grid对界面的变化的适应也是最好的。
5 Canvas
形如:
<Canvas>
<Button Canvas.Left="10" Canvas.Top="10">(10, 10)</Button>
<Button Canvas.Left="120" Canvas.Top="30">(120, 30)</Button>
</Canvas>
这样的会创建一个Canvas布局,其中放置了两个按钮。Canvas与之前不同的是要在其中放置对象要制定对象的精确位置,使用Canvas.Left和Canvas.Top来确定元素的位置,当然这里的值是逻辑坐标而不是像素坐标。另外Canvas中,若有重叠的对象,则可以通过Canvas.ZIndex指定对象的Z序,来确定那个对象在最上面。
上面这5中布局是最长用的布局容器,不过要想很好的使用这几种布局还需要几个属性 ,下面简单介绍这几个属性:
1 HorizontalAlignment和VerticalAlignment:前者确定对象的水平方向对其方式,后者确定对象的垂直方向对其方式。前者可取值为:Left、Center、Right和Stretch。后者可取值为:Top、Center、Bottom和Stretch。这连个属性的值都是相对于对象所在单元格中的对其方式,在StackPanel和Grid中表现最为明显;
2 HorizontalContentAlignment和VerticalContentAlignment:与上面的两个雷同,不过是用来确定内容控件中内容对象的对齐方式;
3 Margin:用来在对象周围加个边框,以使对象与其他对象分开;
4 Padding:控制内容控件中内容对象与内容控件边框之间的距离;
5 Height/Width:分别确定元素的宽度和高度;
6 MaxHeight/MaxWidth/MinHeight/MinWidth:确定元素的最小和最大宽度和高度