Windows GUIプログラミング入門4 画面レイアウト(1)

# ■はじめに
今回は画面レイアウトの基本についてです。
別画面の表示方法も少しやります。

[注意]
これまでの回で説明済みの操作方法等は、説明を省略したり簡略化している場合があります。

# ■開発環境
* Windows 10
* Visual Studio Community 2015 Update 3
* .NET Framework 4.x

# ■StackPanel

## ◇縦並び

プロジェクトを新規作成して、画面デザイナのウィンドウの白い部分（Grid）を右クリック、
「レイアウトの種類の変更」 - 「StackPanel」を選択します。
![wbg4-01.png](https://qiita-image-store.s3.amazonaws.com/0/142879/8f872471-2d6e-068c-02b7-32d441dbb764.png)

タグが`Grid`から`StackPanel`に変わりました。
直接タグを書き換えてもよいです。
![wbg4-02.png](https://qiita-image-store.s3.amazonaws.com/0/142879/5a3f1212-0ce0-bc7e-c315-25b3e3f70bf4.png)

ツールボックスの`Button`を画面デザイナの白い部分（StackPanel）にドラッグ＆ドロップします。
![wbg4-03.png](https://qiita-image-store.s3.amazonaws.com/0/142879/6f956f3a-76a6-f41a-17de-c19d6397a89b.png)

Buttonタグのx:Nameを削除します。
`<Button Content="Button"/>`

Buttonタグをコピペ増殖して、以下のように書き換えます。

```Xml
<StackPanel>
    <Button Content="Button"/>
    <Button Content="Button" Margin="10"/>
    <Button Content="Button" Margin="10" Width="150"/>
    <Button Content="Button" Margin="10" Width="70" Height="50"/>
    <Button Content="Button" Margin="10" Width="70" Height="50" HorizontalAlignment="Left"/>
</StackPanel>
```

画面デザイナではこのように、ボタンが自動的に縦に並んで表示されます。
![wbg4-04.png](https://qiita-image-store.s3.amazonaws.com/0/142879/b57aebb1-0ea2-6645-ab5a-2ba46161e7f5.png)

`Margin`プロパティは他のコントロールとの余白です。
`Margin`プロパティの指定方法のバリエーションは、 [こちらの記事](http://qiita.com/Kosen-amai/items/75136edba4f8ef90d26f "Xamlメモ　Marginプロパティ - Qiita") 参照。

`HorizontalAlignment`プロパティは水平方向の位置指定で、`Left`,`Center`,`Right`,`Stretch`の中から選べます。
既定値は`Stretch`です。
`VerticalAlignment`プロパティは垂直方向の位置指定で、`Top`,`Center`,`Bottom`,`Stretch`の中から選べます。
既定値は`Stretch`です。
![wbg4-05.png](https://qiita-image-store.s3.amazonaws.com/0/142879/f47de8d0-671e-f8b2-d665-b2c4e906e6c2.png)

## ◇横並び

もう一つ`StackPanel`を追加してみましょう。
`Button`タグの並びの一番下に`<StackPanel>`と入力します。
![wbg4-06.png](https://qiita-image-store.s3.amazonaws.com/0/142879/268b2862-a42b-cb19-d070-d6f44d69544a.png)

途中まで入力すれば候補が出てくるので選択します。
![wbg4-07.png](https://qiita-image-store.s3.amazonaws.com/0/142879/07a7fc69-df1e-5945-4587-502c948dc95b.png)

`>`まで入力すると、自動的に`</StackPanel>`まで入力してくれます。
![wbg4-08.png](https://qiita-image-store.s3.amazonaws.com/0/142879/7b59b93e-fcbb-7d09-8a75-eee156ad2780.png)

以下のように書き換えます。

```Xml
<StackPanel Orientation="Horizontal">
    <Button Content="横並び" Margin="5"/>
    <Button Content="横並び" Margin="5"/>
    <Button Content="横並び" Margin="5"/>
</StackPanel>
```

![wbg4-09.png](https://qiita-image-store.s3.amazonaws.com/0/142879/00b49c3a-7f60-1fd3-25b2-c83f08c2165e.png)


`StackPanel`の`Orientation`プロパティが`Horizontal`だと横並びになります。
既定値は縦並びの`Vertical`です。

# ■Grid

## ◇行

次は`Grid`を使ってみます。
ソリューションエクスプローラーでプロジェクトを右クリック、「追加」 - 「新しい項目」を選択。
![wbg4-10.png](https://qiita-image-store.s3.amazonaws.com/0/142879/d24aaa9b-5d8d-a816-90fd-11a82dc03bcd.png)

「ウィンドウ（WPF）」を選択し、名前に`GridWindow1.xaml'を入力し、「追加」ボタンを押します。
![wbg4-10_2.png](https://qiita-image-store.s3.amazonaws.com/0/142879/971890cd-9394-2076-dce2-be725e06754a.png)


`Grid`タグの中に以下を入力します。
`RowDefinition`を3つ書いたので3行のグリッドになります。

```Xml
<Grid.RowDefinitions>
    <RowDefinition/>
    <RowDefinition/>
    <RowDefinition/>
</Grid.RowDefinitions>
```

![wbg4-11.png](https://qiita-image-store.s3.amazonaws.com/0/142879/3888f018-0e44-b093-5902-f4cb787ac03a.png)

`Grid`タグの中、`RowDefinitions`定義の下あたりに`Button`タグを書きます。

```Xml
<Button Grid.Row="0" Content="1行目" Margin="10"/>
<Button Grid.Row="1" Content="2行目" Margin="10"/>
<Button Grid.Row="2" Content="3行目" Margin="10"/>
```

`Grid.Row`で何行目に配置するかを指定します。
一番上の行に配置したいなら0、二番目なら1を指定します。
既定値は0です。なので`Grid.Row="0"`は省略可能です。

カラム指定は後で説明します。
![wbg4-20.png](https://qiita-image-store.s3.amazonaws.com/0/142879/9aafd73b-4af3-dbf7-006f-3f9baaa081f7.png)


![wbg4-12.png](https://qiita-image-store.s3.amazonaws.com/0/142879/76e9d18f-5e35-9fb2-140f-44a7f6a56691.png)

## ◇行の高さ指定

`RowDefinition`に高さの指定を付け加えてみます。

```Xml
<Grid.RowDefinitions>
    <RowDefinition Height="80"/>
    <RowDefinition Height="auto"/>
    <RowDefinition/>
</Grid.RowDefinitions>
```

1行目はピクセル指定、2行目の`auto`は中のコントロールのサイズに合わせた行の高さになります。
3行目は何も指定していないので、既定値の`1*`になり、使用可能なスペースいっぱいに広がります。
![wbg4-13.png](https://qiita-image-store.s3.amazonaws.com/0/142879/23f2b8d3-1c34-dd98-9600-573b96e17dc5.png)

`*`指定の例をもう少し見ていきましょう。

```Xml
<Grid.RowDefinitions>
    <RowDefinition Height="4*"/>
    <RowDefinition Height="2*"/>
    <RowDefinition Height="1*"/>
</Grid.RowDefinitions>
```

この指定の意味は、`1*`を基準として、`2*`はその2倍、`4*`は4倍のスペースを占めるということです。
![wbg4-14.png](https://qiita-image-store.s3.amazonaws.com/0/142879/7090a04d-5901-9d0a-c4d2-e421ea3495d6.png)

次の例です。

```Xml
<Grid.RowDefinitions>
    <RowDefinition/>
    <RowDefinition Height="0.5*"/>
    <RowDefinition Height="*"/>
</Grid.RowDefinitions>
```

この指定は、1行目と3行目が`1*`で、2行目がその半分の高さになっています。
`*`は`1*`と同じです。

![wbg4-15.png](https://qiita-image-store.s3.amazonaws.com/0/142879/6df12575-c214-8f03-f3ce-35a33a9c68d9.png)

## ◇列（カラム）

`Grid`のサンプルの最後に、行と列（カラム）両方使った例をやります。
先ほどと同じように、新しい項目でウィンドウを1つ追加してください。
名前は`GridWindow2.xaml`にし、以下のように入力します。
エクスプローラー風の画面レイアウトです。

```Xml:GridWindow2.xaml
<Window x:Class="WpfApplication4.GridWindow2"
        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:WpfApplication4"
        mc:Ignorable="d"
        Title="GridWindow2" Height="300" Width="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition/>
            <RowDefinition Height="auto"/>
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="0.4*"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Button Content="ツールバー"
                Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"/>
        <Button Content="フォルダツリー"
                Grid.Row="1" Grid.Column="0"/>
        <Button Content="ファイル一覧"
                Grid.Row="1" Grid.Column="1"/>
        <Button Content="ステータスバー"
                Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2"/>
    </Grid>
</Window>
```

見やすさのため、`Row`,`Column`が0のものも明示的に書いていますが、以下のように省略することもできます。

```Xml
<Button Content="ツールバー" Grid.ColumnSpan="2"/>
<Button Content="フォルダツリー" Grid.Row="1"/>
<Button Content="ファイル一覧" Grid.Row="1" Grid.Column="1"/>
<Button Content="ステータスバー" Grid.Row="2" Grid.ColumnSpan="2"/>
```

画面デザイナではこのように表示されます。
![wbg4-21.png](https://qiita-image-store.s3.amazonaws.com/0/142879/d5529aa4-6cb5-8576-2ee3-8d608e8a7cf9.png)

カラム定義も行と大体同じ感じです。
`Grid.ColumnDefinitions`タグの中に必要な分だけ`ColumnDefinition`タグを定義します。
ツールバーとステータスバーは2カラム分使っていますが、`Grid.ColumnSpan`指定をすることでセル結合のようなことができます。
HTMLのテーブルの`colspan`と同じようなものです。
行方向のセル結合は`Grid.RowSpan`で指定します。

# ■別画面の表示
せっかく複数画面を作ったので、メイン画面から表示してみます。
`MainWindow.xaml`の画面デザイナで適当にボタンをダブルクリックします。
作成されたボタンクリックのイベントハンドラに以下を入力します。

```Csharp
var window = new GridWindow2();
window.Show();
```

ツールバーの「開始」を押します。
画面が表示されたら、イベントハンドラを設定したボタンを押します。
![wbg4-22.png](https://qiita-image-store.s3.amazonaws.com/0/142879/36bd2f51-5099-0fb0-4229-297a41cf4f54.png)

GridWindow2が表示されました。
![wbg4-23.png](https://qiita-image-store.s3.amazonaws.com/0/142879/b6e9ec68-d239-2ea7-7f09-be9c6ef7e419.png)


# ■その他レイアウト
他にも`Canvas`とか`DockPanel`とか`WrapPanel`とかありますが、とりあえず`StackPanel`と`Grid`を覚えておけば大丈夫です。

おしまい

---

# ■参考サイト
* [パネルの概要 - MSDN](https://msdn.microsoft.com/ja-jp/library/ms754152.aspx)
* [StackPanel クラス - MSDN](https://msdn.microsoft.com/ja-jp/library/system.windows.controls.stackpanel.aspx)
* [Grid クラス - MSDN](https://msdn.microsoft.com/ja-jp/library/system.windows.controls.grid.aspx)
* [Canvas クラス - MSDN](https://msdn.microsoft.com/ja-jp/library/system.windows.controls.canvas.aspx)
* [DockPanel クラス - MSDN](https://msdn.microsoft.com/ja-jp/library/system.windows.controls.dockpanel.aspx)
* [WrapPanel クラス - MSDN](https://msdn.microsoft.com/ja-jp/library/system.windows.controls.wrappanel.aspx)

---

[＜＜ 最初の記事](http://qiita.com/Kosen-amai/items/f9e3df2aa80363f5af5b "Windows GUIプログラミング入門1 メッセージボックス表示") 　 [＜ 前の記事](http://qiita.com/Kosen-amai/items/1ef3685a0178e134320a "Windows GUIプログラミング入門3 各種設定") 　 [次の記事 ＞](http://qiita.com/Kosen-amai/items/f2451acb2addd221193f "Windows GUIプログラミング入門5 画面レイアウト(2)、画面遷移(1)")