StackPanel面板是最简单的布局容器之一。该面板简单地再单行或单列中以堆栈形式放置其子元素。
例如,分析下面的窗口,该窗口包含4个按钮:
<Window x:Class="Layout.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Simple StackPanel" Height="300" Width="300"> <StackPanel> <Label>Button StackPanel</Label> <Button>Button1</Button> <Button>Button2</Button> <Button>Button3</Button> <Button>Button4</Button> </StackPanel> </Window>
下图显示了最终结果图:
默认情况下,StackPanel面板按自上而下的顺序排列元素,使每个元素的高度适合它的内容。在这个示例中,这意味着标签和按钮的大小刚好足够适应他们内部包含的文本。所有元素都被拉伸到StackPanel面板的整个宽度,这也是窗口的宽度。如果加宽窗口,StackPanel面板也会变宽,并且按钮也会拉伸自身以适应变化。
通过设置Orientation属性,StackPanel面板也可用于水平排列元素:
<StackPanel Orientation="Horizontal">
现在,元素指定他们的最小宽度(足够适合它们所包含的文本)并拉伸至容器面板的整个高度,根据窗口的当前大小,这可能导致一些元素不适应,如下图所示:
一、布局属性
尽管布局由容器决定,但子元素仍有一定的决定权。实际上,布局面板支持一小组布局属性,以便与子元素结合使用,在下表中列出了布局属性。
表 StackPanel布局属性
所有这些属性都是从FrameworkElement基类继承而来,所以在WPF窗口中可使用的所有图形小组件都支持这些属性。
这些属性列表就像它所么以偶包含的属性一样值得注意。如果查找熟悉的鱼位置相关的属性,例如Top属性、Right属性以及Location属性,是不会找到他们的。这是因为大多数布局容器(Canvas控件除外)都使用自动布局,并未提供显示定位元素的能力。
二、对齐方式
为理解这些属性的工作原理,可进一步分析前面的简单StackPanel面板。在这个示例中——有一个垂直方向的StackPanel面板——VerticalAlignment属性不起作用,因为所有元素的高度都自动调整为刚好满足各自需要。但HorizontalAlignment属性非常重要,它决定了各个元素在行的什么位置。
通常,对于Label控件,HorizontalAlignment属性的值默认为Left;对于Button控件,HorizontalAlignment属性的值默认为Stretch。这也是为什么每个按钮的宽度被调整为整列的宽度的原因所在。但可以改变这些细节:
<Window x:Class="Layout.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Simple StackPanel" Height="300" Width="300"> <StackPanel > <Label HorizontalAlignment="Center">Button StackPanel</Label> <Button HorizontalAlignment="Left">Button1</Button> <Button HorizontalAlignment="Right">Button2</Button> <Button>Button3</Button> <Button>Button4</Button> </StackPanel> </Window>
最终显示结果如下所示:
三、边距
在StackPanel示例中,在当前情况下存在一个明显的问题。设计良好的窗口不只是包含元素——还应当在元素之间包含一定的额外空间。为了添加而外的空间并使StackPanel面板示例中的按钮不那么紧密,可为控件设置边距。
当设置边距时,可为所有边设置相同的宽度,如下所示:
<Button Margin="5">Button3</Button>
相应地,也可为控件的每个边以左、上、右、下的顺序设置不同的宽度,如下所示:
<Button Margin="5,10,10,5">Button4</Button>
在代码中,是代码中使用Thickness进行设置:
cmd.Margin=new Thickness(5);
为得到正确的控件边距,需要采用一些艺术手段,因为需要考虑相邻控件边距设置的相互影响。例如,如果两个按钮堆在一起,位于最高处的按钮的底部边距设置为5,而下面按钮的顶部边距也设置为5,那么这两个按钮之间就有10个单位的空间。
理想情况下,能尽可能始终如一地保持不同的边距设置,避免为不同的边设置不同的值。例如,在StackPanel示例中,为按钮和面板本身设置相同的边距比较合适。如下所示:
<Window x:Class="Layout.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Simple StackPanel" Height="300" Width="300"> <StackPanel Margin="3" > <Label Margin="3" HorizontalAlignment="Center">Button StackPanel</Label> <Button Margin="3" HorizontalAlignment="Left">Button1</Button> <Button Margin="3" HorizontalAlignment="Right">Button2</Button> <Button Margin="3">Button3</Button> <Button Margin="3">Button4</Button> </StackPanel> </Window>
最终显示效果如下所示:
四、最小尺寸、最大尺寸以及显示的尺寸设置
每个元素都提供了Height和Width属性,用来显示地指定元素大小。但这种设置一般不是一个号主意。相反,如果必要,应当使用最大尺寸和最小尺寸属性,将控件限制在正确的范围内。
如下代码所示:
<Window x:Class="Layout.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Simple StackPanel" Height="300" Width="300"> <StackPanel Margin="3" > <Label Margin="3" HorizontalAlignment="Center">Button StackPanel</Label> <Button Margin="3" MaxWidth="200" MinWidth="100">Button1</Button> <Button Margin="3" MaxWidth="200" MinWidth="100">Button2</Button> <Button Margin="3" MaxWidth="200" MinWidth="100">Button3</Button> <Button Margin="3" MaxWidth="200" MinWidth="100">Button4</Button> </StackPanel> </Window>
运行效果如下图所示已经修改窗体大小
当StackPanel调整按钮的尺寸时,需要考虑以下部分信息:
- 最小尺寸。每个按钮的尺寸始终不能小于最小尺寸
- 最大尺寸。每个按钮的尺寸始终不能超过最大尺寸(除非执行错误操作,使最大尺寸比最小尺寸还小)
- 内容。如果按钮中的内容需要更大的宽度,StackPanel容器会尝试扩展按钮(可以通过检查DesiredSized属性确定所需的按钮大小,该属性返回最小宽度或内容的宽度,返回两者中较大的那个)。
- 容器大小。如果最小宽度大于StackPanel面板的宽度,按钮的一部分将被剪裁掉。否则,不允许按钮比StackPanel面板更宽,即使不能适合按钮表面的所有文本。
- 水平对齐方式。因为默认情况下按钮的HorizontalAlignment属性设置为Stretch,所以StackPanel面板尝试反映按钮所期望的尺寸(以适合其内容)以及对齐方式的设置。
理解这个过程的关键在于,要认识到最小尺寸和最大尺寸设置了绝对界限。在这个界限内,StackPanel面板尝试反映按钮所期望的尺寸以及对齐方式的设置。通过调整上面示例的宽度,查看窗口中的按钮变化情况。
五、Border控件
Border控件不是布局面板,而是非常便于使用的元素,经常与布局面板一起使用。
Border类非常简单。它只能包含一段嵌套内容(通常是布局面板),并为其添加背景或在其周围添加边框。为了深入理解Border控件,只需要账务下表中列出的属性就可以。
下面是一个具有轻微圆角效果的简单边框,该边框位于一组按钮的周围,这组按钮包含在一个StackPanel面板中:
<Window x:Class="Layout.BorderWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="BorderWindow" Height="300" Width="300"> <Border Margin="5" Padding="5" Background="LightGoldenrodYellow" BorderBrush="SteelBlue" BorderThickness="3,5,3,5" CornerRadius="3" VerticalAlignment="Top"> <StackPanel> <Button Margin="3">Button1</Button> <Button Margin="3">Button2</Button> <Button Margin="3">Button3</Button> <Button Margin="3">Button4</Button> </StackPanel> </Border> </Window>
运行效果图下图所示: