WPF 標準コントロールデモアプリ › UniformGrid

UniformGrid Layout

UniformGrid は、子を同じ大きさのセルに、行ごとに左から右へ並べるパネルです。指定するのは行数か列数だけで、行や列の定義はありません。

行と列がいくつになるか

UniformGrid は System.Windows.Controls.Primitives 名前空間にあります。Rows・Columns・FirstColumn の既定値は 0 です。Rows と Columns の 0 は「自動で決める」という意味で、どちらも設定しないと、UniformGrid は正方形の配置を作ります。デモアプリの 5 つのラベルでは 3 行 3 列(300 × 200 のグリッドで 100 × 66.67 のセル)になり、ラベルは上の 2 行に入って 3 行目は空きました。一方を設定するとその数が固定され、もう一方は必要なだけ増えます。300 × 200 のグリッドで、5 つのラベルは Columns="1" で 300 × 40 のセルの 5 行に、Columns="2" で 150 × 66.67 のセルの 3 行になりました。Rows="1" では 5 列の 1 行に、Rows="2" では 2 行 3 列になりました。

Collapsed の子はセルを使いません。5 つのうち 2 つ目を折りたたんで Columns="2" にすると、3 つ目のラベルが 2 つ目のセルに入り、行数は 2 のままでした。グリッドから外したい子は折りたたみます。

収まらない子はどこへ置かれるか

Rows と Columns は、どちらか一方だけを設定します。両方を設定して子が収まらなくても、余った子は捨てられず、グリッドの外に置かれます。Rows="2"・Columns="2" で 5 つのラベルを置くと、5 つ目は 4 つのセルの下の (0, 200)、高さ 200 のグリッドの外に置かれました。

FirstColumn が 0 に戻される条件

FirstColumn は、最初の子の前に空けるセルの数です。カレンダーで、月の 1 日をその曜日の位置から始めるときに使います。デモアプリの初期値は Columns="3"・9 つのラベルで 1 です。1 つ目のラベルは 2 つ目のセルの (100, 0) に置かれ、3 つ目のラベルが 2 行目の先頭になり、グリッドは 4 行になりました。

FirstColumn は Columns より小さくします。FirstColumn が 3 や 4 と Columns 以上のときは、グリッドが 0 に戻しました。レイアウト後の値は 0 で、1 つ目のラベルは (0, 0)、グリッドは 3 行でした。0 に戻すとバインドも外れます。デモアプリと同じくテキストボックスにバインドした場合、4 を入力すると 0 になってバインドが外れ、その後 1 を入力しても 0 のままでした。

セルの大きさの決まり方

セルはすべて同じ大きさです。幅 300 に広げた 3 列のグリッドでは、幅 150 の子があってもセルの幅は 100 でした。大きさを内容に合わせる場合は、最も幅の広い子がすべてのセルの大きさを決めます。同じグリッドを横の StackPanel に入れると、セルの幅は 150 になりました。1 つだけ大きい子があると、すべてのセルがその大きさになります。

空いたセルと ZIndex

2 列に 1 つのラベルを置くと、空いたセルのヒットテストで、Background が既定値の null では何も当たらず、Transparent ではグリッドが当たりました。子が重なったときは Panel.ZIndex で順序が決まります。デモアプリでは 2 つ目のラベルの上余白が -15 で、1 つ目に重なっています。ZIndex が 1 と 2 では 2 つ目が、3 と 2 では 1 つ目が上になりました。

条件 計測値
名前空間 / 既定値: Rows、Columns、FirstColumn System.Windows.Controls.Primitives / 0, 0, 0
Label 5 個、300 x 200、Columns=1(デモの初期値) 5 行 x 1 列、セル 300 x 40
Label 5 個、300 x 200、Columns=2 3 行 x 2 列、セル 150 x 66.67
Label 5 個、300 x 200、Rows=1(デモの初期値) 1 行 x 5 列、セル 60 x 200
Label 5 個、300 x 200、Rows=2 2 行 x 3 列、セル 100 x 100
Label 5 個、300 x 200、どちらも指定なし 3 行 x 3 列(子は 2 行)、セル 100 x 66.67
Label 5 個、Rows=2、Columns=2(セル 4 つ)、300 x 200: 4 個目 / 5 個目の位置 (150, 100) / (0, 200)
デモの FirstColumn=1、Columns=3、Label 9 個: Item1 / Item3 の位置、形 (100, 0) / (0, 50)、4 行 x 3 列
FirstColumn=3、Columns=3: Item1 の位置、形、レイアウト後の FirstColumn (0, 0)、3 行 x 3 列、0
FirstColumn=4、Columns=3: Item1 の位置、形、レイアウト後の FirstColumn (0, 0)、3 行 x 3 列、0
文字列 "4" にバインド(デモ): FirstColumn、バインド、続けて文字列を "1" に: FirstColumn、Item1 の位置 0、バインドは外れる、0、(0, 0)
Label 5 個、Columns=2、Item2 が Collapsed: Item3 の位置 / 形 (150, 0) / 2 行 x 2 列、セル 150 x 100
Columns=3、幅 150 の子: 300 に広げる / 内容に合わせる 100 x 100 / 150 x 100
Columns=2 に Label 1 個、Background=null: 空いたセルのヒットテスト (なし)
Columns=2 に Label 1 個、Background=Transparent: 空いたセルのヒットテスト Grid
デモの ZIndex の Label(Item2 の上の Margin -15)、ZIndex 1 と 2: 上にあるもの Item2
デモの ZIndex の Label(Item2 の上の Margin -15)、ZIndex 3 と 2: 上にあるもの Item1

行、列、FirstColumn、セルの大きさ。.NET 10 / Windows 11 で計測。

デモアプリで試す

デモアプリの UniformGrid のページ。左にコントロールの一覧、右に最初の節の Columns

デモアプリの UniformGrid のページには、Columns、Rows、FirstColumn、Background、ZIndex の欄があります。各欄の下の「Show Code」リンクで、その欄の XAML を表示できます。次の XAML は、FirstColumn の欄(UniformGridUsageControl.xaml)から、スタイル、周囲の GroupBox、テキストボックスの入力制限のビヘイビア、9 つのうち 6 つのラベルを省き、名前空間の宣言を加えたものです。

<StackPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <TextBox x:Name="FirstColumnTextBox" Text="1" />
  <TextBox x:Name="ColumnsForFirstColumnTextBox" Text="3" />

  <UniformGrid x:Name="FirstColumnUniformGrid"
               Columns="{Binding Text, ElementName=ColumnsForFirstColumnTextBox}"
               FirstColumn="{Binding Text, ElementName=FirstColumnTextBox}">
    <Label BorderBrush="Black" BorderThickness="1" Content="Item1" />
    <Label BorderBrush="Black" BorderThickness="1" Content="Item2" />
    <Label BorderBrush="Black" BorderThickness="1" Content="Item3" />
  </UniformGrid>
</StackPanel>

関連するコントロールと記事

ソースコードと計測の方法

このページの挙動の記述は、すべて .NET 10 / Windows 11 で実際に動かして確かめたものです。計測には、このサイトのスクリーンショット生成ツールの UniformGridDemoScene を使い、デモアプリと同じラベル(枠 1)で試しました。グリッドは Measure と Arrange でレイアウトし、行と列は子の位置から数えました。大きさは、計測したマシンでの値です。

GitHub で UniformGrid のソースコードを見る →