【WPF(XAML)C#3】StackPanel/DockPanel/WrapPanelの違い

セクション3もTextBlockに続き、実務で頻繁に使用するPanel系の説明となります。Panelの使用用途としてはGridと同じように画面の区画を構成するのに役立ちます。セクション1や新規ファイルではGridでくくっていましたが実はDockPanelでくくるプロジェクトも多いです。

DockPanel

このPanelはDockPanel単体では効果はなく、その中の指定にDockPanel.Dockを指定する事により、効果を発揮します。以下のXAMLソースを見てください。

<DockPanel Grid.Row="1" Grid.Column="0">

    <StackPanel DockPanel.Dock="Bottom">
        <Label Content="今日の天気予報" HorizontalAlignment="Center" Template="{StaticResource aaab}" FontSize="20" FontWeight="Bold" Foreground="OrangeRed" />
    </StackPanel>

    <StackPanel DockPanel.Dock="Left">
        <Label Content="今日の天気予報" HorizontalAlignment="Center" Template="{StaticResource aaab}" FontSize="20" FontWeight="Bold" Foreground="OrangeRed" />
        <Border BorderBrush="Red" BorderThickness="2" CornerRadius="8" Height="50" Width="140">
            <DockPanel>
                <Image DockPanel.Dock="Left" Source="Image/16_2_19.png" Margin="0,0,-10,0"/>
                <TextBlock Text="26℃" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="30"/>
            </DockPanel>
        </Border>

        <Border BorderBrush="Red" BorderThickness="2" CornerRadius="8" Height="50" Width="140">
            <StackPanel Orientation="Horizontal">
                <Image Source="Image/16_2_19.png" Margin="0,0,-10,0"/>
                <TextBlock Text="26℃" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="30"/>
            </StackPanel>
        </Border>
    </StackPanel>
    
    <StackPanel DockPanel.Dock="Right">
        <Label Content="今日の天気予報" HorizontalAlignment="Center" Template="{StaticResource aaab}" FontSize="20" FontWeight="Bold" Foreground="OrangeRed" />
    </StackPanel>

    <StackPanel DockPanel.Dock="Top">
        <Label Content="今日の天気予報" HorizontalAlignment="Center" Template="{StaticResource aaab}" FontSize="20" FontWeight="Bold" Foreground="OrangeRed" />
    </StackPanel>

    <Label Content="今日の天気予報" HorizontalAlignment="Center" Template="{StaticResource aaab}" FontSize="20" FontWeight="Bold" Foreground="OrangeRed" />
</DockPanel>

DockPanelの下に各StackPanelを配置し、各々にDockPanel.Dockを指定し、一番最後にStackPanelも何も指定しないLabelがいます。これを実行すると以下のようなレイアウトになります。

例えばDockPanel.Dock=Bottomのエリアは必ず一番下に配置されますので用途としては各画面を制御するためのボタンにしたりとかが想定されます。DockPanel.Dock=Top一番上DockPanel.Dock=LeftRightの後に指定すれば上記画像のように3つ並べたような配置が完成します。

ではDockPanel.Dock=TopをLeftやRightより先に定義するとどうなるのでしょうか?その場合は下のようになります。

先にTopが上を占拠して、その下にLeft/Rightが来ます。この使い方の場合はファイル名や全体のタイトル等を表示する。といった使い方が想定できます。

といったようにDockPanel.Dockの指定は早く定義した方から優先度が決まっていくので順番には注意しましょう。

StackPanel

こちらはDockPanelのような使い方はしない箱みたいなものだと考えておきましょう。上のソースを見るとDockPanel.Dockで定義した所は全てStackPanelでくくっています。それにより、「今日の天気予報」の文字が前回説明したTemplateによってキレイに装飾されています。しかしStackPanelでくくっていないLabelの場合はどうでしょうか?

Templateの装飾が上下に伸びてしまい、想定通りの動作になっていない事がわかります。こういう部分はStackPanelという箱を使用してLabel等を入れてあげないといけないのでセットで使用することを覚えておくといいでしょう。

他にもあるDockPanelの使い方とStackPanelの違い

上に貼り付けたコードの中から以下のコードを抜粋します。

<StackPanel DockPanel.Dock="Left">
    <Label Content="今日の天気予報" HorizontalAlignment="Center" Template="{StaticResource aaab}" FontSize="20" FontWeight="Bold" Foreground="OrangeRed" />
    <Border BorderBrush="Red" BorderThickness="2" CornerRadius="8" Height="50" Width="140">
        <DockPanel>
            <Image DockPanel.Dock="Left" Source="Image/16_2_19.png" Margin="0,0,-10,0"/>
            <TextBlock Text="26℃" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="30"/>
        </DockPanel>
    </Border>

    <Border BorderBrush="Red" BorderThickness="2" CornerRadius="8" Height="50" Width="140">
        <StackPanel Orientation="Horizontal">
            <Image Source="Image/16_2_19.png" Margin="0,0,-10,0"/>
            <TextBlock Text="26℃" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="30"/>
        </StackPanel>
    </Border>
</StackPanel>

これは上の画像にあった今日の天気予報に「晴れと気温」が書かれているエリアです。上はDockPanelを使って、画像にDockPanel.Dockを定義したもの、下はStackPanelにOrientation=”Horizontal”を定義して横に表示できるようにしたものです。

StackPanelに何も指定しない場合はStackPanel内は下に改行して表示されます。縦でなく、横にしたい場合はOrientationを定義しましょう。こちらも画面を作る上で結構使用します。

結果は上の画像を見ると一目瞭然ですがDockPanelを使用した方は晴れの画像と気温の位置が明確に分かれていますがStackPanelの方は晴れと気温がかぶってしまっていてうまくいってない事がわかります。Marginを使って文字と画像をずらす事は可能ですが、可読性も悪くなりますのでこの場合は素直にDockPanelを活用しましょう。

WrapPanel

こちらはStackPanelやDockPanelより使用頻度は低いですが、箱の中のコンテンツが一番右に行ったときにはみ出しだりせずに、折り返してくれるPanelです。折り返したいStackPanelと思ってくれれば大丈夫です。以下のコードを見てください。

<StackPanel Grid.Row="0" Grid.Column="1">
    <StackPanel >
        <TextBlock Text="あああああああああああああ"/>
    </StackPanel>
    <StackPanel >
        <TextBlock Text="いいいいいいいいいいいいい"/>
    </StackPanel>
    <StackPanel >
        <TextBlock Text="ううううううううううううう"/>
    </StackPanel>
</StackPanel>

<WrapPanel Grid.Row="1" Grid.Column="1">
    <StackPanel >
        <TextBlock Text="あああああああああああああ"/>
    </StackPanel>
    <StackPanel >
        <TextBlock Text="いいいいいいいいいいいいい"/>
    </StackPanel>
    <StackPanel >
        <TextBlock Text="ううううううううううううう"/>
    </StackPanel>
</WrapPanel>

このコードを実行すると以下のようになります。

上(StackPanel)は定義する毎に改行されていますが下(WrapPanel)の方は改行されずに一番右に行ったら2行目に表示されています。それでは先ほど説明した上のStackPanelに改行しないようにするOrientation=”Horizontal”を指定するとどうなるのでしょうか?その場合は下の画像のようになります。

いかがでしょうか?改行はされなくなりましたが、うううううの後改行されず、はみ出してしまっています。折り返してほしい時はWrapPanelを使用するのがベターです。

WrapPanelの使用が想定される場面は例えばウィンドウの画面サイズの横幅を小さくしてもギリギリまで表示させたい時に使います。ただ、折り返した事によって他のレイアウトに影響が出てしまう事もありますのでこの辺は色々試してベストな配置を見つけてみてください。

以上です。いかがでしょうか?これで3つのパネルの役割を把握して頂ければ幸いです。次回もこれまた大事なDataGridのお話をしたいと思います。それでは~。