五. 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 Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="300" />
</Grid.ColumnDefinitions>
</Grid>
注意:這里介紹一下Grid高度、寬度的幾種定義方式:
| 名稱 |
說明 |
| 絕對尺寸 |
就是給一個實際的數字,但通常將此值指定為整數,像上圖中中那樣 |
| 自動(Autosizing) |
值為Auto,實際作用就是取實際控件所需的最小值 |
| StarSizing |
值為*或N*,實際作用就是取盡可能大的值,當某一列或行被定義為*則是盡可能大,當出現多列或行被定義為*則是代表幾者之間按比例方設置尺寸 |
第一種,固定長度——寬度不夠,會裁剪,不好用。單位pixel。
第二種,自動長度——自動匹配列中最長元素的寬度。
第三種,比例長度——*表示占用剩余的全部寬度;兩行都是*,將平分剩余寬度;像上面的一個2*,一個*,表示前者2/3寬度。
2) 跨越多行和多列
<Rectangle Fill="Silver" 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>
使用GridSplit控件結合Grid控件實現類似於WinForm中SplitContainer的功能,這個大家在WinForm當中經常用到,我們也不多做介紹。
4) XAML代碼實現下圖效果(用XAML):

<Window x:Class="WpfApp1.WindowGridDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WindowGridDemo" Height="300" Width="400">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="61*"/>
<RowDefinition Height="101*"/>
<RowDefinition Height="108*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="139"/>
<ColumnDefinition Width="184*"/>
<ColumnDefinition Width="45*" />
<ColumnDefinition Width="250*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.ColumnSpan="1" Text="第一行,第一列,占1列" Background="Red" HorizontalAlignment="Center" />
<Button Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="3" Grid.RowSpan="2" Content="從第1行第2列開始,占兩行,三列" />
<Button Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="4" Content="第3行,第1列開始,占4列" />
<Button Grid.Row="1" Name="btnAddByCode" Click="btnAddByCode_Click" >后台代碼生成(第2行第1列)</Button>
</Grid>
</Window>
5) 下圖,以C#代碼實現:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace WpfApp1
{
/// <summary>
/// WindowGridDemo.xaml 的交互邏輯
/// </summary>
public partial class WindowGridDemo : Window
{
public WindowGridDemo()
{
InitializeComponent();
}
public void btnAddByCode_Click(object sender, RoutedEventArgs e)
{
Grid grid = new Grid();
grid.Width = Double.NaN; //相當於在XAML中設置Width="Auto"
grid.Height = Double.NaN; //相當於在XAML中設置Height="Auto"
//把grid添加為窗體的子控件
this.Content = grid;
//列一
ColumnDefinition cd1 = new ColumnDefinition();
cd1.Width = new GridLength(139);
grid.ColumnDefinitions.Add(cd1);
//列二
ColumnDefinition cd2 = new ColumnDefinition();
cd2.Width = new GridLength(1, GridUnitType.Star);
grid.ColumnDefinitions.Add(cd2);
//列三
ColumnDefinition cd3 = new ColumnDefinition();
cd3.Width = new GridLength(2, GridUnitType.Star);
grid.ColumnDefinitions.Add(cd3);
//行一
RowDefinition row1 = new RowDefinition();
row1.Height = new GridLength(61);
grid.RowDefinitions.Add(row1);
//行二
RowDefinition row2 = new RowDefinition();
row2.Height = new GridLength(1, GridUnitType.Star);
grid.RowDefinitions.Add(row2);
//行三
RowDefinition row3 = new RowDefinition();
row3.Height = new GridLength(200);
grid.RowDefinitions.Add(row3);
//把單元格添加到grid中
Rectangle r0c1 = new Rectangle();
r0c1.Fill = new SolidColorBrush(Colors.Gray);
r0c1.SetValue(Grid.ColumnProperty, 0);
r0c1.SetValue(Grid.RowProperty, 0);
grid.Children.Add(r0c1);
Rectangle r1c23 = new Rectangle();
r1c23.Fill = new SolidColorBrush(Colors.Yellow);
r1c23.SetValue(Grid.ColumnProperty, 1);
r1c23.SetValue(Grid.ColumnSpanProperty, 2);
r1c23.SetValue(Grid.RowProperty, 1);
r1c23.SetValue(Grid.RowSpanProperty, 2);
grid.Children.Add(r1c23);
}
}
}
六、 UniformGrid
介紹了前面的Grid,接下來介紹的這個UniformGrid 就是Grid的簡化版,每個單元格的大小相同,不需要定義行列集合。每個單元格始終具有相同的大小,每個單元格只能容納一個控件,將自動按照定義在其內部的元素個數,自動創建行列,並通常保持相同的行列數。UniformGrid 中沒有Row 和Column 附加屬性,也沒有空白單元格。
與Grid布局控件相比,UniformGrid布局控件很少使用。Grid面板是用於創建簡單乃至復雜窗口布局的通用工具。UniformGrid面板是一個一種更特殊的布局容器,主要用於在一個刻板的網格中快速地布局元素。
下面用XAML代碼實現一個示例,該示例使用4個按鈕填充UniformGrid面板。:

<Window x:Class="WpfApp1.WindowUniformGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WindowUniformGrid" Height="300" Width="300">
<Grid>
<UniformGrid Rows="2" Columns="2">
<Button>第一個(0,0)</Button>
<Button>第二個(0,1)</Button>
<Button>第三個(1,0)</Button>
<Button Name="btnAddByCode" Click="btnAddByCode_Click">第四個(1,1)</Button>
</UniformGrid>
</Grid>
</Window>
下面使用C#代碼實現10個TextBlock的控件的布局。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace WpfApp1
{
/// <summary>
/// WindowUniformGrid.xaml 的交互邏輯
/// </summary>
public partial class WindowUniformGrid : Window
{
public WindowUniformGrid()
{
InitializeComponent();
}
public void btnAddByCode_Click(object sender, RoutedEventArgs e)
{
UniformGrid wp = new UniformGrid();
//把wp添加為窗體的子控件
this.Content = wp;
wp.Margin = new Thickness(0, 0, 0, 0);
wp.Background = new SolidColorBrush(Colors.Red);
//遍歷增加Rectangles
TextBlock block;
for (int i = 0; i <= 10; i++)
{
block = new TextBlock();
block.Text = string.Format("第{0}個", i);
wp.Children.Add(block);
}
}
}
}

