Grid コントロール

Last Updated 2011/09/21


Grid コントロールはその名前のとおり、グリッド、つまり、格子状に子要素を配置可能にするコントロールです。HTML 構文の TABLE 要素を想起すれば分かりやすいかもしれません。


Grid

上図の左は以下のコードのデザイン時の状態、右は実行時の状態です。デザイン時はグリッド線が薄いグレーで表示されています。実行時は ShowGridLines プロパティに true を指定して、グリッド線を表示する設定にしています。ただし、このグリッド線はデザイン時のチェック用に用意された機能なので、常に点線で描画されます。もし、立派なグリッド線が必要であれば、それに対応する子要素を用意しなければなりません。

<Grid VerticalAlignment="Top" HorizontalAlignment="Left" ShowGridLines="True"
      Width="250" Height="100" Margin="10">
  <Grid.ColumnDefinitions>
    <ColumnDefinition />
    <ColumnDefinition />
    <ColumnDefinition />
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition />
    <RowDefinition />
    <RowDefinition />
  </Grid.RowDefinitions>

  <TextBlock FontSize="16" FontWeight="Bold" Grid.ColumnSpan="3" Grid.Row="0">2005 年度製品の出荷実績></TextBlock>
  <TextBlock FontSize="12" FontWeight="Bold" Grid.Row="1" Grid.Column="0">第 1 四半期</TextBlock>
  <TextBlock FontSize="12" FontWeight="Bold" Grid.Row="1" Grid.Column="1">第 2 四半期</TextBlock>
  <TextBlock FontSize="12" FontWeight="Bold" Grid.Row="1" Grid.Column="2">第 3 四半期</TextBlock>
  <TextBlock Grid.Row="2" Grid.Column="0">50,000</TextBlock>
  <TextBlock Grid.Row="2" Grid.Column="1">100,000</TextBlock>
  <TextBlock Grid.Row="2" Grid.Column="2">150,000</TextBlock>
  <TextBlock FontSize="12" FontWeight="Bold" Grid.ColumnSpan="3" Grid.Row="3">合計:300,000</TextBlock>
</Grid>

Grid コントロールのプロパティとメソッドについてはクラスライブラリを見てもらうとして、上記のコードを見てのとおり、Grid コントロールの構築はまず、ColumnDefinitions および RowDefinitions プロパティで列と行とを追加するところから始まります。次の子要素がどのグリッドに属するかを Column および Row プロパティで指定します。複数の列または行にまたがって子要素を配置する場合は、ColumnSpan および RowSpan プロパティで指定します。

グリッド線

前項で触れたグリッド線を追加してみましょう。ベストな方法かどうかは分かりませんが、下図では Border コントロールを利用しました。

Grid2

  <Grid VerticalAlignment="Top" HorizontalAlignment="Left" Width="250" Height="100" Margin="10">
    <Grid.ColumnDefinitions>
      <ColumnDefinition />
      <ColumnDefinition />
      <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
      <RowDefinition />
      <RowDefinition />
      <RowDefinition />
      <RowDefinition />
    </Grid.RowDefinitions>

    <TextBlock FontSize="16" FontWeight="Bold" Grid.ColumnSpan="3" Grid.Row="0">2005 年度製品の出荷実績</TextBlock>

    <Border Grid.Row="1" Grid.Column="0" BorderThickness="2,2,1,1" BorderBrush="Orange">
      <TextBlock FontSize="12" FontWeight="Bold" >第 1 四半期</TextBlock>
    </Border>
    <Border Grid.Row="1" Grid.Column="1" BorderThickness="1,2,1,1" BorderBrush="Orange">
      <TextBlock FontSize="12" FontWeight="Bold" >第 2 四半期</TextBlock>
    </Border>
    <Border Grid.Row="1" Grid.Column="2" BorderThickness="1,2,2,1" BorderBrush="Orange">
      <TextBlock FontSize="12" FontWeight="Bold" >第 3 四半期</TextBlock>
    </Border>

    <Border Grid.Row="2" Grid.Column="0" BorderThickness="2,1,1,1" BorderBrush="Orange">
      <TextBlock FontSize="12" FontWeight="Bold" >50,000</TextBlock>
    </Border>
    <Border Grid.Row="2" Grid.Column="1" BorderThickness="1,1,1,1" BorderBrush="Orange">
      <TextBlock FontSize="12" FontWeight="Bold" >100,000</TextBlock>
    </Border>
    <Border Grid.Row="2" Grid.Column="2" BorderThickness="1,1,2,1" BorderBrush="Orange">
      <TextBlock FontSize="12" FontWeight="Bold" >150,000</TextBlock>
    </Border>
    <Border Grid.Row="3" Grid.ColumnSpan="3" BorderThickness="2,1,2,2" BorderBrush="Orange">
      <TextBlock FontSize="12" FontWeight="Bold" >合計:300,000</TextBlock>
    </Border>

  </Grid>

サイズの指定(アスタリスク "*" の使い方)

Grid3

上記のコードでは設定しませんでしたが、グリッドのセルの幅と高さを指定することができます。そのとき、絶対値で設定することはもちろんできますが、"Auto" とアスタリク "*" を指定することができます。"Auto" はセルの幅または高さを自動調整、つまり、セルのコンテンツのサイズに合わせてセルのサイズを自動的に調整します。下図でいえば、Grid(0,0) がそうです。

アスタリスク "*" は WPF ではスター値 "star value" と呼んでいるもので、Grid コントロールのサイズに合わせてセルのサイズを自動調整するときに使います。上記のコード例では、セルのサイズを設定していませんから Grid コントロールの幅と高さを列数と行数とで等分したサイズになっています。

左図の上の図では、Grid(0,0) 以外のセルのサイズはすべて "*" です。したがって、Grid コントロールの高さから Grid(0,0) のセルのサイズを差し引いた残りのサイズを等分します。

中央の図は、2 番目の列の幅のみ "2*" を指定しました。この場合、残りのサイズを 4 等分し、2 番目のに列は 2 つ分を割り当てます。

下の図は、3 番目の列および行のセルの幅および高さとして、"Auto" を指定しました。

以下のコードの実行結果は、一番上の図です。

<Border Width="300" Height="120" BorderBrush="Black" BorderThickness="1">
  <Grid Width="300" Height="120" ShowGridLines="True">
    <Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition Width="*"/>
    <ColumnDefinition Width="*"/>
    <ColumnDefinition Width="*"/>
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="*"/>
    <RowDefinition Height="*"/>
    <RowDefinition Height="*"/>
  </Grid.RowDefinitions>

  <TextBlock Grid.Column="0" Grid.Row="0">Grid (0,0)</TextBlock>
  <TextBlock Grid.Column="1" Grid.Row="1">Grid (1,1)</TextBlock>
  <TextBlock Grid.Column="2" Grid.Row="2">Grid (2,2)</TextBlock>
  <TextBlock Grid.Column="3" Grid.Row="3">Grid(3,3)</TextBlock>
  </Grid>
</Border>

GridSplitter コントロール

GridSplitter コントロールは Grid コントロール用スプリッタコントロールです。下図の上は、以下のコードを実行したところで、下はスプリッタをマウスを使って移動したところです。プロパティの解説は省略しますが、このコントロールの動作方法を決める重要なプロパティは、ResizeBehavior プロパティと ResizeDirection プロパティです。

Splitter

<Border Width="200" Height="80" BorderBrush="Black" BorderThickness="1">
  <Grid Width="200" Height="80">
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="40"/>
      <ColumnDefinition/>
      <ColumnDefinition Width="60"/>
    </Grid.ColumnDefinitions>

    <Border Grid.Column="0" Background="LightBlue" />
    <GridSplitter Grid.Column="0" Background="Blue" Width="2" HorizontalAlignment="Right" VerticalAlignment="Stretch"/>
    <Border Grid.Column="1" Background="Orange" />
    <GridSplitter Grid.Column ="1" Background="Blue" Width="2" HorizontalAlignment="Right" VerticalAlignment="Stretch"/>
    <Border Grid.Column="2" Background="Aliceblue" />
  </Grid>
</Border>

UniformGrid コントロール

このコントロールは Grid コントロールと関連するかのような名前になっていますが、まったく性格の異なるもので、同一サイズのセルに子要素を格納するグリッドコントロールです。

このコントロールはどういうふうに使うと便利かと考えてみたところ、下図のような使い方はどうでしょうか。たとえば、GroupBox コントロールに複数の RadioButton コントロールを配置するとき、コントロールの位置を微調整することなく、均等に割り付けてくれます。コードでは radioButton1 にチェックを入れていますが、ほかのボタンを選択するとラジオボタンらしくチェックを変更してくれます。

UniformGrid

 

<Border Width="120" Height="100" BorderThickness="1" BorderBrush="Blue">
  <UniformGrid Width="120" Height="100" Columns="1" Rows="5">
    <RadioButton Width="100" Height="25" IsChecked="true">radioButton1</RadioButton>
    <RadioButton Width="100" Height="25">radioButton2</RadioButton>
    <RadioButton Width="100" Height="25">radioButton3</RadioButton>
    <RadioButton Width="100" Height="25">radioButton4</RadioButton>
    <RadioButton Width="100" Height="25">radioButton5</RadioButton>
  </UniformGrid>
</Border>

最後に一言

WPF SDK や WEB サイトなどで公開されているサンプルプロジェクトの多くは、コントロールを配置するために Grid コントロールを使うケースが多いようです。しかし、私は基本的に使いません。Grid コントロールを使えば、デザイン時にはツールボックスからコントロールを運んでくるだけでいいので便利なのですが、コードを見るときにはひどく面倒です。

また、Grid コントロールはコントロールを配置するための処理が面倒なので、パフォーマンスが低下することを免れません。処理速度としてもっとも効率的なのは Canvas コントロールです。なぜかと言うと、座標値を明示的に設定するので、コントロールの位置やサイズを計算する必要がないからです。

フォームに配置するコントロールがすごく多くなる場合は、Grid コントロールにバラバラに配置することは避けるべきです。関連性の深いコントロールを一つのコンテナコントロールにまとめて、それを Grid コントロールに配置することを考えてください。

ところで、

Grid コントロールはほかのパネルコントロールとは異なる性質を持ちます。というのは、ほかのパネルコントロールは内包するコントロールを水平方向とか垂直方向に並べますが、Grid コントロールは行とカラムを指定しない場合は同じ位置に複数のコントロールを重ねることができます。

以下は部分的なコードですが、青色の矩形の Visibility プロパティに Hidden を指定していますので、画面上では赤色の矩形しか見えません。Visibility プロパティを Visible に変更すれば青色の矩形が見えることになります。

<Grid>
  <Rectangle Width="100" Height="100" Fill="Red" />
  <Rectangle Width="100" Height="100" Fill="Blue" Visibility="Hidden" />
</Grid>

コントロールを同じ位置に重ねると使えるテクニックの幅が広がる可能性があります。この性質はぜひ覚えておいてください。


−以上−