XAML学习笔记——Layout(二)

   本篇随笔将简单介绍两种基本的布局——Grid布局和VariableSizedWrapGrid布局。

  Grid布局

  顾名思义,Grid布局将布局容器以行和列的分割方法拆分成若干单元格,然后通过指定子元素所属单元格的行编号(Grid.Row)与列编号(Grid.Column)的方式将一个或多个子元素排列在指定的单元格中,从而以表格的形式排列子元素。从功能和设计方式上讲,Grid布局排列子元素的行为和HTML中的 table 类似,但是使用方式更加灵活。Grid布局在开发过程中多用于表单的开发设计,并且经常用于其他布局的父容器嵌套使用,如以后会介绍的SplitView、ViewBox布局等。

  定义行(Rows)和列(Columns)

  依据定义,我们想要搞定Grid布局最重要的就是搞定行和列。具体来讲包括行和列的添加以及行和列尺寸的相关定义。

  首先要根据需求确定Grid布局所需的行数与列数,Grid布局默认只包含一行一列,如果要添加其他的行和列就必须在Grid中的RowDefinitionsColumnDefinitions两个属性集合中分别添加相应数量的子元素,下面的代码展示了如何定义一个包含四行两列的Grid。

 1 <Grid>
 2     <Grid.RowDefinitions>
 3         <RowDefinition />
 4         <RowDefinition />
 5         <RowDefinition />
 6         <RowDefinition />
 7     </Grid.RowDefinitions>
 8     <Grid.ColumnDefinitions>
 9         <ColumnDefinition />
10         <ColumnDefinition />
11     </Grid.ColumnDefinitions>
12 </Grid>

  确定好行和列的数量之后,我们就要为行和列的尺寸属性赋值。

  在实际开发中我们关心的是行的高度(Height)属性和列的宽度(Width)属性,以行高为例,有三种方式可以为其赋值,分别为:

  • Fixed 即此行高度为固定数值(据官方数据一个单位为1/96 英寸??)
  • Auto  此行的高度完全取决于其包含元素的高度。
  • Star (*)  按各行比例分配相应高度,举个例子就很容易明白了:
  1. 若将n行的高度都赋值为"*",那么每行的高度为n行所占总高度的1/n;
  2. 如果只有两行,第一行高度赋值为"3*"而第二行高度赋值为"5*",那么第一行就占两行总高度的3/8而第二行占5/8;
  3. 如果某些行的高度值以其他两种方式赋值,则不参与按比例赋值的计算;

  用同样的方法为列的宽度属性赋值,接着上面的例子将行和列的尺寸赋值后,代码如下:

 1 <Grid>
 2     <Grid.RowDefinitions>
 3         <RowDefinition Height="Auto" />
 4         <RowDefinition Height="Auto" />
 5         <RowDefinition Height="*" />
 6         <RowDefinition Height="28" />
 7     </Grid.RowDefinitions>
 8     <Grid.ColumnDefinitions>
 9         <ColumnDefinition Width="Auto" />
10         <ColumnDefinition Width="200" />
11     </Grid.ColumnDefinitions>
12 </Grid>

 

   向Grid中添加元素

   放在Grid中的元素必须放在<Grid>开闭标签之间,通过为元素添加Grid.Column和Grid.Row属性的方式来确定元素的位置,两个属性的值分别为Grid的列索引号和行索引号(从0开始)。

    继续为上面的例子中添加几个控件,代码如下:

 

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
        <RowDefinition Height="50" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="200" />
    </Grid.ColumnDefinitions>
    <TextBlockGrid.Row="0" Grid.Column="0" Content="Name:"/>
    <TextBlockGrid.Row="1" Grid.Column="0" Content="E-Mail:"/>
    <TextBlock Grid.Row="2" Grid.Column="0" Content="Comment:"/>
    <TextBox Grid.Column="1" Grid.Row="0" Margin="3" />
    <TextBox Grid.Column="1" Grid.Row="1" Margin="3" />
    <TextBox Grid.Column="1" Grid.Row="2" Margin="3" />
    <Button Grid.Column="1" Grid.Row="3" HorizontalAlignment="Right" 
            MinWidth="80" Margin="3" Content="Send"  />
</Grid>

 

   要想继续调整元素在单元格内的位置,可以通过上篇随笔中介绍的HorizontalAlignment、VerticalAlignment和Margin三个属性来实现,抄袭一张图片:

 

  调整之后示例代码的运行结果如下:

  

   

  在code中实现Grid 

     用xaml实现Grid布局虽然可以将行和列的定义与应用分开,但是代码十分冗长写起来真的是很痛苦,每一行和列都需要手动添加,尤其是行和列的定义部分显得很长。如果在实际开发中遇到相对复杂表单时,可以考虑在code中应用for循环来搞定。

  在code中可以通过GridLength类实现行和列的尺寸属性定义,三种定义的code实现方式如下:

Auto

GridLength.Auto

Star

new GridLength(1,GridUnitType.Star)

Fixed

new GridLength(100,GridUnitType.Pixel)

   给个简单的实例代码:

1 Grid grid = new Grid();
2  
3 ColumnDefinition col1 = new ColumnDefinition();
4 col1.Width = GridLength.Auto;
5 ColumnDefinition col2 = new ColumnDefinition();
6 col2.Width = new GridLength(1,GridUnitType.Star);
7  
8 grid.ColumnDefinitions.Add(col1);
9 grid.ColumnDefinitions.Add(col2);

  以上就是关于Grid布局的简介。

  VariableSizedWrapGrid布局

  和上面介绍的Grid布局一样, VariableSizedWrapGrid 也是将布局容器按照行和列平均分割成若干单元格,并将所有的子元素排列其中。不同点在于VariableSizedWrapGrid的行和列数量是可变的。换一种理解方式,其本质就是最简单的布局方式——“流式布局”,只不过借用grid的展现方式而已。用流式布局的理解方式就很容易明白搞定VariableSizedWrapGrid布局的关键在于两点——确定子元素的“流动方向”(Orientation)和子元素“流动范围”(MaximumRowsOrColumns )。

  确定元素“流动方向”

  通过Orientation属性可以控制元素的排列方向。当赋值为Vertical时,元素按照竖直方向从左到右排列。此属性的默认值即为Vertical。

  给个例子:

 1 <VariableSizedWrapGrid Orientation="Vertical" Margin="20">
 2         
 3         <VariableSizedWrapGrid.Resources>
 4             <Style TargetType="Button">
 5                 <Setter Property="Background"
 6                            Value="LightBlue"/>
 7                 <Setter Property="Margin"
 8                         Value="20"/>
 9                 <Setter Property="Padding"
10                         Value="10"/>
11             </Style>
12         </VariableSizedWrapGrid.Resources>
13        
14         <Button Content="Button1"/>
15         <Button Content="Button2"/>
16         <Button Content="Button3"/>
17         <Button Content="Button4"/>
18         <Button Content="Button5"/>
19         <Button Content="Button6"/>
20         <Button Content="Button7"/>
21         <Button Content="Button8"/>
22         <Button Content="Button9"/>
23         <Button Content="Button0"/>
24         
25     </VariableSizedWrapGrid>

  效果图如下:

  若将Orientation属性改为Horizontal,则元素按照水平方向从左至右排列,效果:

  这个属性实在是很好理解,和其他“流式布局”相同,当窗口缩放时,元素的排列的行数和列数也会随之出现相应的变化。如果想要限定元素排列的行数或者列数就要用到MaximumRowsOrColumns属性了。

  确定元素“流动范围”

  通过对MaximumRowsOrColumns属性赋值可以限定元素的排列范围,但是这个属性的实际含义却取决于Orientation属性的值,借用上面的例子,当元素按竖直方向排列,并且为MaximumRowsOrColumns属性赋值“2”时:

 

1     <VariableSizedWrapGrid Margin="20" Orientation="Vertical" MaximumRowsOrColumns="2">
2         ......
3         
4     </VariableSizedWrapGrid>

效果如下:

   结果所有Button整齐的排列成两行,并且位置固定,不随着窗口的缩放改变位置。可见当Orientation="Vertical"时,MaximumRowsOrColumns约束的是元素排列的最大“行数”。如果把元素的排列方向改为水平,其他不变:

1     <VariableSizedWrapGrid Margin="20" Orientation="Horizontal" MaximumRowsOrColumns="2">
2         ......
3         
4     </VariableSizedWrapGrid>

则变为:

   则结果所有Button整齐的排列成两列,位置依然固定。由此可见当Orientation="Horizontal"时,MaximumRowsOrColumns约束的是元素排列的最大“列数”。

   虽然结果明了,但是过程比较费解。。为什么不把行和列分开约束呢??网上有关此布局的先关资料实在有限,本人也是通过实战方式得出结论,专业性肯定差点,如果查到相关资料我会第一时间修正。总之,有待继续学习。。好吧,暂时会用就行。。

  跨单元格排列元素

  以上例子中的元素都是按照单个单元格进行排,我们也可以使用VariableSizedWrapGrid.ColumnSpan和VariableSizedWrapGrid.RowSpan两个属性使元素跨单元格排列。举一个极简单的例子,将上面例子中的Button1和Button2修改如下:

<Button VariableSizedWrapGrid.RowSpan="2" Content="Button1"/>
<Button VariableSizedWrapGrid.ColumnSpan="2" Content="Button2"/>

效果如下:

  这两个布局的基本用法先介绍到这里。。一篇随笔介绍两个布局貌似篇幅有点大。。下篇随笔准备介绍两种简单的布局——StackPanel和RelativePanel。

 

posted @ 2016-01-20 19:08  lovevv  阅读(453)  评论(0编辑  收藏  举报