本文通过5个实例来演示WPF中5个常用布局控件Grid、StackPanel、DockPanel、Canvas、WrapPanel的使用方法。
实例1 使用Grid进行布局
使用Grid将画面分割成5行5列,并在1行1列、3行2列、3行3列及5行1列四个位置上放置4个背景色不同的TextBox控件,且5行1列的TextBox控件横跨4列。
下面给出画面的设计图及详细代码。
图1 使用Grid进行布局
下面是详细代码:
<Window x:Class="WpfPanelExp.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">
<Grid IsManipulationEnabled="True">
<Grid.RowDefinitions>
<RowDefinition Height="3*"></RowDefinition>
<RowDefinition Height="2*"></RowDefinition>
<RowDefinition Height="2*"></RowDefinition>
<RowDefinition Height="2*"></RowDefinition>
<RowDefinition Height="2*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="110"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox Text="1行1列 Grid.Row=0 Grid.Column=0(可以省略,省略时默认为1行1列)" Grid.Row="0" Grid.Column="0" Background="Violet" TextWrapping="Wrap" />
<TextBox Text="3行2列 Grid.Row=2 Grid.Column=1" Grid.Row="2" Grid.Column="1" Background="Beige" TextWrapping="Wrap" />
<TextBox Text="3行3列 Grid.Row=2 Grid.Column=2" Grid.Row="2" Grid.Column="2" Background="AliceBlue" TextWrapping="Wrap" />
<TextBox Text="5行1列 Grid.Row=4 Grid.Column=0 跨4列 Grid.ColumnSpan=4" Grid.Row="4" Grid.Column="0" Background="WhiteSmoke" Grid.ColumnSpan="4" />
</Grid>
</Window>
下面将结合实例1的设计图来解释代码。
1 如何定义Grid的行和列?
使用Grid的RowDefinitions和ColumnDefinitions属性可以定义Grid的行和列,他们分别是RowDefinition和ColumnDefinition的集合,集合包含的RowDefinition和ColumnDefinition对象的数量表示Grid含有的行数和列数,实例中的RowDefinitions包含5个RowDefinition对象,说明Grid包含5行,同理可知,Grid包含5列。
2 如何定义行高和列宽?
使用RowDefinition的Height属性定义行的高度,使用ColumnDefinition的Width属性定义列的宽度。
注意:RowDefinition不存在Width属性,ColumnDefinition 不存在Height属性。
Height属性和Width属性可以被设置成以下三类值:
- 绝对值:double数值加单位(当采用像素(pixel,简写成px)作为单位时可以省略单位,因为像素是默认单位)
- 比例值:double数值后加上一个星号(此种情况不需要加单位)
- 自动值: 字符串Auto。
在我们的实例中,这三类值都有被使用到,请往下看:
- 使用绝对值的地方:定义列宽的时候,前四列的宽度被设置为“110”、“100”、“100”、“100”,这里并没有显示给出单位,则说明采用的是默认单位像素。
- 使用比例值的地方:定义行高的时候,高度分别被定义为“3*”、“2*”、“2*”、“2*”、“2*”,意思是说将Grid的总高度分割成11份(3+2+2+2+2),而第一行高度占其中的3份,剩余4行高度各占2份。
- 使用自动值的地方:定义列宽的时候,最后一列的宽度被设置为“Auto”,说明该列宽度的实际值将由该列内的控件的宽度来决定,控件将把列“撑”到合适的宽度,而在本例中,该列内并不包含控件,则列宽为0。
3 怎样将控件安排在合适的位置上?
在定义好了行和列的Grid中安放控件的工作和老师安排座位的工作真有异曲同工之处啊,只是没有“家长”为了自己的孩子能得到一个好位子,给我送点小礼物而已。
为控件安排“座位”,其实就是给控件指定行和列:
- 使用Grid.Row与Grid.Column属性指定控件的行和列;
- 使用Grid.RowSpan与Grid.ColumnSpan定义控件跨越的行数或列数。
完成“排座位”这项神圣的工作,还需要遵循几点简单的原则:
- 行和列的值都是从0开始计数,如例子中的第1行第1列的控件的Row与Column属性值被设置为“0”;
- 当某个控件所处的行的编号为0,则可以省略Row属性的设置代码,同理,当某控件所处的列的编号为0时,则可以省略Column属性的设置代码。
4 设置行高或者列宽时,除了可以使用像素作为单位外,还能使用哪些单位?
- inch(英寸):简写为in,1inch=96pixel
- centimeter(厘米):简写为cm,1cm=(96/2.54)pixel
- Point(点):简写为pt,1pt=(96/72)pixel
实例2 使用StackPanel进行布局
使用StackPanel完成画面控件的布局操作,在画面中完成古诗“相思”的显示,其中标题与作者水平排列显示,而古诗内容纵向排列显示。
具体的布局效果如下图所示。并在后面给出详细的布局代码。
图2 使用StackPanel进行布局
下面是详细代码:
<Window x:Class="WpfPanelExp.StackPanelExp"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="StackPanelExp" Height="300" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="4*"></RowDefinition>
<RowDefinition Height="6*"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock Text="相思" FontSize="24" FontFamily="MS UI Gothic" Margin="10,5,0,10" Background="Fuchsia" />
<TextBlock Text=" [作者]王维" FontSize="24" FontFamily="MS UI Gothic" Margin="10,5,0,10" Background="Aqua" />
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Vertical" HorizontalAlignment="Center">
<TextBlock Text="红豆生南国" FontSize="24" FontFamily="MS UI Gothic" Margin="10,5,0,10" />
<TextBlock Text="春来发几枝" FontSize="24" FontFamily="MS UI Gothic" Margin="10,5,0,10" />
<TextBlock Text="愿君多采撷" FontSize="24" FontFamily="MS UI Gothic" Margin="10,5,0,10" />
<TextBlock Text="此物最相思" FontSize="24" FontFamily="MS UI Gothic" Margin="10,5,0,10" />
</StackPanel>
</Grid>
</Window>
实例2中,先使用Grid将画面分割成上下两部分,两部分的高度比为2:3。
关于Grid的使用在实例1中已经说明过,这里将重点说明的是StackPanel控件的使用方法,下面将结合实例2的代码来探讨StackPanel的使用。
StackPanel可以将内部元素在横向或者纵向上紧密排列。使用StackPanel布局得到的效果与堆积木类似,当抽掉下面的积木时,上面的积木会自动补上。与生活中的“堆积木”稍有不同的是,生活中的堆积木往往指的是从下往上堆,而使用StackPanel布局不仅能够从下往上堆,还可以是从左往右堆。而决定积木堆积方向的是StackPanel的Orientation属性,该属性可以被设置为“Horizontal”或者“Vertical”,分别表示横向累积和纵向累积。实例2中,分别使用了两个StackPanel控件,第一个StackPanel控件的Orientation属性被设置为“Horizontal”,表示横向堆积,最终的效果是“标题”和“作者”被水平排列显示。实例2中第二个StackPanel控件的Orientation属性被设置为“Vertical”,表示纵向堆积,所以显示的内容项是纵向排列的。
除了Orientation属性外,Stack控件还具有HorizontalAlignment属性和VerticalAlignment属性。HorizontalAlignment属性定义StackPanel控件内部元素水平方向上的对齐方式,可以取值“Left”“Center”“Right”“Stretch”;而VerticalAlignment属性定义内部元素竖直方向上的对齐方式,可以取值“Top”“Center”“Bottom”“Stretch”。实例2中两个StackPanel控件的HorizontalAlignment属性都被设置为“Center”,其效果是两个StackPanel控件内部的元素位于水平方向的中央位置。
StackPanel控件的布局工作正是借助于Orientation属性、HorizontalAlignment属性及VerticalAlignment属性的协同工作来完成的。
实例3 使用DockPanel进行布局
实例3使用DockPanel控件将画面分割成顶部、下左、下右3部分,其中顶部显示古诗标题和作者,下部左半部分显示古诗内容,右半部分显示古诗解析。
设计效果如下图所示。
图3 使用DockPanel进行布局
下面给出详细的实现代码。
<Window x:Class="WpfPanelExp.DockPanelExp"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DockPanelExp" Height="300" Width="300">
<Grid>
<DockPanel>
<TextBox Text="相思 [作者]王维" DockPanel.Dock="Top" Height="25" Background="Aqua" />
<TextBox Text="红豆生南国 春来发几枝 愿君多采撷 此物最相思" TextWrapping="Wrap" DockPanel.Dock="Left" Width="80" Background="SeaShell" />
<TextBox Text="《相思》是唐代诗人王维的作品,是一首借咏物而寄相思的诗作。此诗写相思之情,却全篇不离红豆,正用其相思子之名以关合相思之情。首句写红豆产地;次句以'发几枝'一问,语极朴实,而又极富形象性,设问自然,则暗逗情怀;三句寄意友人'多采撷',言在此而意在彼;末句点明其相思属性,且用一'最'字推达极致,则'多采撷'的理由自见,而自身所寄之意亦深含其中。全诗极为明快,却又委婉含蓄,语浅而情深,相传当时即为人谱曲传唱,流行江南。" TextWrapping="Wrap" Background="LawnGreen" />
</DockPanel>
</Grid>
</Window>
通过为DockPanel内的元素附加上DockPanel.Dock属性来达到布局元素的效果,DockPanel.Dock属性可以被设置为“Left”“Top”“Right”“Button”四个值。
实例3中,DockPanel包含的内部元素是三个TextBox控件:
- 第一个TextBox控件的DockPanel.Dock属性被设置为“Top”,Height属性为25,表明将第一个TextBox控件位于DockPanel的顶部,并占去25像素的高度;
- 第二个TextBox控件的DockPanel.Dock属性被设置为“Left”,Width属性设置为80,表明第二个TextBox控件位于DockPanel内部剩下部分的左部,占去80像素的宽度;
- DockPanel中最后一个TextBox控件的DockPanel.Dock属性被忽略,它将把DockPanel内部所有剩余的空间占满,不过要想达到这种效果,需要将DockPanel的LastChildFill属性设置为“True”,在实例3中并没有找到这样的设置代码,因为DockPanel的LastChildFill属性的默认值就为“True”。
实例4 使用Canvas进行布局
实例4使用Canvas完成布局,显示古诗“相思”。
设计效果图如下所示。
图4 使用Canvas进行布局
下面是实例4的详细代码。
<Window x:Class="WpfPanelExp.CanvasExp"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CanvasExp" Height="300" Width="300">
<Grid>
<Canvas>
<TextBlock Text="相思" FontSize="24" FontFamily="MS UI Gothic" Margin="0,5,0,5" Background="Fuchsia" Canvas.Left="100" Canvas.Top="10"/>
<TextBlock Text="[作者]王维" FontSize="24" FontFamily="MS UI Gothic" Margin="0,5,0,5" Background="Aqua" Canvas.Left="90" Canvas.Top="45" />
<TextBlock Text="红豆生南国" FontSize="24" FontFamily="MS UI Gothic" Margin="0,5,0,5" Canvas.Left="85" Canvas.Top="75"/>
<TextBlock Text="春来发几枝" FontSize="24" FontFamily="MS UI Gothic" Margin="0,5,0,5" Canvas.Left="85" Canvas.Top="105"/>
<TextBlock Text="愿君多采撷" FontSize="24" FontFamily="MS UI Gothic" Margin="0,5,0,5" Canvas.Left="85" Canvas.Top="135"/>
<TextBlock Text="此物最相思" FontSize="24" FontFamily="MS UI Gothic" Margin="0,5,0,5" Canvas.Left="85" Canvas.Top="165"/>
</Canvas>
</Grid>
</Window>
下面将结合代码来说明Canvas的使用。
Canvas的中文意思是“画布”,使用Canvas布局与在Windows Form窗体中布局控件的方式基本一致,通过为“画布”上的元素附加属性Canvas.Left和Canvas.Top来完成内部元素的定位。这里的Canvas.Left和Canvas.Top属性与Windows Form窗体控件的Left和Top属性类似,Canvas.Left属性表示距离“画布”左边的距离,而Canvas.Top属性表示距离“画布”顶部的距离。实例4中,“画布”内包含四个TextBlock控件,并依次设置每个控件的Canvas.Left和Canvas.Top属性即可完成布局工作。
实例5 使用WrapPanel进行布局
实例5使用WrapPanel对画面中的10个数字按钮进行布局,看起来是不是很像手机的按键啊,试着拨出你的号码吧,呵呵。
图5 使用WrapPanel进行布局
下面是实例5的详细代码。
<Window x:Class="WpfPanelExp.WrapPanelExp"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WrapPanelExp" Height="300" Width="300">
<Grid>
<WrapPanel Orientation="Vertical">
<Button Width="60" Height="60" Content="1"/>
<Button Width="60" Height="60" Content="2"/>
<Button Width="60" Height="60" Content="3"/>
<Button Width="60" Height="60" Content="4"/>
<Button Width="60" Height="60" Content="5"/>
<Button Width="60" Height="60" Content="6"/>
<Button Width="60" Height="60" Content="7"/>
<Button Width="60" Height="60" Content="8"/>
<Button Width="60" Height="60" Content="9"/>
<Button Width="60" Height="60" Content="0"/>
</WrapPanel>
</Grid>
</Window>
其实通过阅读代码,感觉新东西不多,单纯的将10个数字按钮包含进WrapPanel控件而已。
那么使用WrapPanel进行布局又有什么特别之处呢?
WrapPanel内部采用的是流式布局,而WrapPanel的Orientation属性设置了其流延伸的方向。同时,可以使用HorizontalAlignment和VerticalAlignment属性控制内部控件的对齐方式。实例4中将Orientation属性设置为“Vertical”,说明内部元素的流延伸的方向为垂直,为了更好的体验一下这种效果,我们可以运行程序,再改变窗体的高度,看看会有什么样效果。
图6 WrapPanel布局效果图一
通过这幅图,大家能发现什么吗?
当WrapPanel的Orientation属性被设置为“Vertical”时,WrapPanel内部垂直方向上显示的元素个数会随着高度的改变而动态调整。
为了理解将WrapPanel的Orientation属性设置为“Horizontal”时的效果,修改WrapPanel的Orientation属性为“Horizontal”,再次运行程序,并修改窗体的宽度,可以得到下面的效果图。
图7 WrapPanel布局效果图二
这时,你又能发现什么呢?
好了,就到这里了,总结有就免了,88。