五. Grid

Grid顾名思义就是“网格”,它的子控件被放在一个一个实现定义好的小格子里面,整齐配列。 Grid和其他各个Panel比较起来,功能最多也最为复杂。要使用Grid,首先要向RowDefinitions和ColumnDefinitions属性中添加一定数量的RowDefinitions和 ColumnDefinitions元素,从而定义行数和列数。而放置在Grid面板中的控件元素都必须显示采用附加属性语法定义其 放置所在的行和列,它们都是以0为基准的整型值,如果没有显式设置任何行或列,Grid将会隐式地将控件加入在第0行第0列。由于Grid的组成并非简单的添加属性标记来区分行列,这也使得用户在实际应用中可以具体到某一单元格中,所以布局起来就很精细了。

Grid的单元格可以是空的,一个单元格中可以有多个元素,而在单元格中元素是根据它们的Z顺序一个接着一个呈现的。与Canvas一样,同一个单元格中的子元素不会与其他元素交互布局,信息——它们仅仅是重叠而已。接下来我们来使用一些实际的代码演示一下如何使用GRID。

1) Grid的列宽与行高可采用固定、自动、按比列三种方式定义

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="40"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
            <ColumnDefinition Width="300"></ColumnDefinition>
        </Grid.ColumnDefinitions>
    </Grid>

注意:这里介绍一下Grid高度、宽度的几种定义方式:

名称 说明
绝对尺寸 就是给一个实际的数字,但通常将此值指定为整数,像上图中中那样
自动(Autosizing) 值为Auto,实际作用就是取实际控件所需的最小值
StarSizing 值为* 或N* ,实际作用就是取尽可能大的值,当某一列或行被定义为* 则是尽可能大,当出现多列或行被定义为*则是代表几者之间按比例设置尺寸

第一种,固定长度——宽度不够,会裁剪,不好用。单位pixel。 第二种,自动长度——自动匹配列中最长元素的宽度。 第三种,比例长度——* 表示占用剩余的全部宽度;两行都是* ,将平分剩余宽度;像上面的一个2* ,一个*,表示前者2/3宽度。

2) 跨越多行和多列

<Rectangle Width="250" Height="40" Fill="Red" Grid.Column="1" Grid.ColumnSpan="3"/>

使用 Grid.ColumnSpan 和 Grid.RowSpan 附加属性可以让相互间隔的行列合并,所以元素也可以跨越多个单元格。

3) 使用 GridSplit 分割

<GridSplitter Height="6" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
                      Grid.Row="2" Grid.Column="2"></GridSplitter>

c3d.club

<Window x:Class="项目6.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:项目6"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="750">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="61*"></RowDefinition>
            <RowDefinition Height="101*"></RowDefinition>
            <RowDefinition Height="108*"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="139"></ColumnDefinition>
            <ColumnDefinition Width="184"></ColumnDefinition>
            <ColumnDefinition Width="45*"></ColumnDefinition>
            <ColumnDefinition Width="250"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <TextBox Background="Red" Text="第一行,第一列,占一列" VerticalAlignment="Center"></TextBox>
        <Button Margin="15" Grid.Column="1" Grid.ColumnSpan="3" Grid.RowSpan="2" Content="从第一行第二列开始,占两行,三列" />
        <Button Margin="25" Grid.Row="1" Name="Button">后台生成代码</Button>
        <Button Margin="30" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="4" Content="第三行,第一列开始,占4列"></Button>
    </Grid>
</Window>

5) 下图,以 C# 代码实现:

c3d.club

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace 项目6 {
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Ok_Click(object sender, RoutedEventArgs e)
        {
            var grid=new Grid();
            grid.Width=Double.NaN;//相当于在XAML中设置Width="Auto"
            grid.Height=Double.NaN;
            Content = grid;
            var cd1=new ColumnDefinition();
            cd1.Width=new GridLength(139);
            grid.ColumnDefinitions.Add(cd1);
            var cd2=new ColumnDefinition();
            cd2.Width=new GridLength(1,GridUnitType.Star);
            grid.ColumnDefinitions.Add(cd2);
            var cd3=new ColumnDefinition();
            cd3.Width=new GridLength(2,GridUnitType.Star);
            grid.ColumnDefinitions.Add(cd3);
            var rd1=new RowDefinition();
            rd1.Height=new GridLength(61);
            grid.RowDefinitions.Add(rd1);
            var rd2=new RowDefinition();
            rd1.Height=new GridLength(1,GridUnitType.Star);
            grid.RowDefinitions.Add(rd2);
            var rd3=new RowDefinition();
            rd1.Height=new GridLength(200);
            grid.RowDefinitions.Add(rd3);
            var rec1=new Rectangle();
            rec1.Fill=new SolidColorBrush(Colors.Gray);
            rec1.SetValue(Grid.ColumnProperty,0);
            rec1.SetValue(Grid.RowProperty,0);
            grid.Children.Add(rec1);
            var rec2=new Rectangle();
            rec2.Fill=new SolidColorBrush(Colors.Yellow);
            rec2.SetValue(Grid.ColumnProperty,1);
            rec2.SetValue(Grid.ColumnSpanProperty,2);
            rec2.SetValue(Grid.RowProperty,1);
            rec2.SetValue(Grid.RowSpanProperty,2);
            grid.Children.Add(rec2);
        }
    }
}

六、 UniformGrid

c3d.club

介绍了前面的 Grid, 接下来介绍的这个 UniformGrid 就是 Grid 的简化版,每个单元格的大小相同,不需要定义行列集合。每个单元格始终具有相同的大小,每个单元格只能容纳一个控件,将自动按照定义在其内部的元素个数,自动创建行列,并通常保持相同的行列数。UniformGrid 中没有 Row 和 Column 附加属性,也没有空白单元格。

与 Grid 布局控件相比,UniformGrid 布局控件很少使用。Grid 面板是用于创建简单乃至复杂窗口布局的通用工具。UniformGrid 面板是一个一种更特殊的布局容器,主要用于在一个刻板的网格中快速地布局元素。

下面用 XAML 代码实现一个示例,该示例使用 4 个按钮填充 UniformGrid 面板。:

    <Grid>
        <UniformGrid Rows="2" Columns="2">
            <Button Margin="50">第一个(0,0)</Button>
            <Button Margin="50">第二个(0,1)</Button>
            <Button Margin="50">第三个(1,0)</Button>
            <Button Margin="50" Name="ButtonAddByCode">第四个(1,1)</Button>
        </UniformGrid>
    </Grid>

下面使用 C# 代码实现 15 个 TextBlock 的控件的布局。

c3d.club

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using System.Windows.Shapes;

namespace 项目6 {
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void ButtonAddByCode_Click(object sender, RoutedEventArgs e)
        {
            var ug = new UniformGrid();
            Content = ug;
            ug.Margin=new Thickness(15);
            ug.Background=new SolidColorBrush(Colors.Yellow);
            TextBlock block;
            for (int i = 0; i < 15; i++)
            {
                block=new TextBlock();
                block.Background=new SolidColorBrush(Colors.AliceBlue);
                block.VerticalAlignment = VerticalAlignment.Center;
                block.HorizontalAlignment = HorizontalAlignment.Center;
                block.Margin=new Thickness(25,25,25,25);
                block.Text = "C# 第" + i.ToString("00")+ "个";
                ug.Children.Add(block);
            }
        }
    }
}