首页 > 代码库 > WPF布局

WPF布局

本文通过5个实例来演示WPF5个常用布局控件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布局不仅能够从下往上堆,还可以是从左往右堆。而决定积木堆积方向的是StackPanelOrientation属性,该属性可以被设置为“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属性的协同工作来完成的。

 

实例使用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”。


实例使用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

WPF布局