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

StackPanel Layout

StackPanel は、子を 1 列または 1 行に順に並べるパネルです。最も単純なパネルですが、大きさの決まり方で最もつまずきやすいパネルでもあります。

並べる方向には無限の大きさを渡す

StackPanel は、並べる方向には子に無限の大きさを渡します。200 × 100 の縦の StackPanel では子は 200 × Infinity で、横の StackPanel では Infinity × 100 で測られました。もう一方の方向では子は引き伸ばされ、40 × 20 を望んだ子は、縦のパネルでは幅 200、横のパネルでは高さ 100 に配置されました。

縦の StackPanel の中の一覧がスクロールしない理由

無限の大きさのため、縦の StackPanel の中の一覧は高さが限られません。高さ 200 の領域に置いた 1000 項目の ListBox は、高さ 200 で 991 スクロールでき、項目を 10 個作りました。同じ領域で縦の StackPanel に入れると、高さが 19964 になってスクロールできず、1000 個すべての項目を作りました。ScrollViewer でも同じことを、下にリンクした記事で示しています。スクロールさせたい一覧は、Grid の行などで高さを限ります。

StackPanel 自体も仮想化しません。高さ 200 の ScrollViewer の中の StackPanel に 1000 個の子を置くと、1000 個すべてが測られました。一方、高さを限った ListBox は、表示する分の項目だけを作りました。長い一覧には StackPanel ではなく ListBox を使います。

子は折り返さず、はみ出した部分は切れる

Orientation の既定値は Vertical で、子は折り返しません。デモアプリの 3 つのラベルを幅 80 の横の StackPanel に並べると、3 つ目のラベルは 94.69 から始まり、パネルの端を越えました。越えた部分は切れます。ClipToBounds は False でしたが、WPF のレイアウトによる切り抜きでパネルは 80 に限られ、端の外の 3 つ目のラベルをヒットテストしても何も当たりませんでした。折り返すには WrapPanel を使います。また、Spacing プロパティはないので、子の間隔は子の Margin で空けます。

空いた場所と ZIndex

デモアプリは高さ 30 の空の StackPanel を表示しています。Background が既定値の null では中央のヒットテストで何も当たらず、そこでのクリックは後ろの要素に届きます。Transparent や色を設定すると、同じヒットテストでパネルが当たりました。

子が重なったときは、Panel.ZIndex でどれを上に描くかが決まります。デモアプリでは 2 つ目のラベルが 1 つ目に 15 重なっています。ZIndex が 1 と 2 では重なった部分で 2 つ目が上に、3 と 2 では 1 つ目が上になりました。順序が決まるのは同じパネルの子どうしだけです。内側のパネルの子に ZIndex="100" を付けても、その内側のパネルの兄弟(ZIndex 0)より下のままでした。

条件 計測値
Orientation の既定値 / Spacing プロパティ Vertical / なし
Vertical、200 x 100 のパネル: 子に渡される大きさ / 配置された子の大きさ(希望は 40 x 20) 200 x Infinity / 200 x 20
Horizontal、200 x 100 のパネル: 子に渡される大きさ / 配置された子の大きさ(希望は 40 x 20) Infinity x 100 / 40 x 100
Horizontal、デモの 3 つの Label、Width 80: 最後の Label の x / ClipToBounds / レイアウトのクリップの幅 94.69 / False / 80
80 の外にある最後の Label のヒットテスト (なし)
高さ 200 の ScrollViewer の中の StackPanel に 1000 個の子: 測定された子の数 1000
高さ 200 に 1000 項目の ListBox、直接: 高さ / ScrollableHeight / 作られた項目の数 200 / 991 / 10
高さ 200 に 1000 項目の ListBox、縦の StackPanel の中: 高さ / ScrollableHeight / 作られた項目の数 19964 / 0 / 1000
高さ 30 の空の StackPanel、Background=null: 中央のヒットテスト (なし)
高さ 30 の空の StackPanel、Background=Transparent: 中央のヒットテスト Panel
高さ 30 の空の StackPanel、Background=AliceBlue: 中央のヒットテスト Panel
デモの Label、ZIndex Item1=1、Item2=2: 重なった部分で上にある要素 Item2
デモの Label、ZIndex Item1=3、Item2=2: 重なった部分で上にある要素 Item1
ZIndex=100 の内側のパネルの子と、内側のパネルの兄弟(ZIndex 0): 上にあるもの OuterSibling

子に渡す大きさ、はみ出し、背景、ZIndex。.NET 10 / Windows 11 で計測。

デモアプリで試す

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

デモアプリの StackPanel のページには、Orientation、Background、ZIndex の 3 つの欄があります。各欄の下の「Show Code」リンクで、その欄の XAML を表示できます。次の XAML は、ZIndex の欄(StackPanelUsageControl.xaml)から、スタイルと周囲の GroupBox を省き、名前空間の宣言を加えたものです。

<StackPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <TextBox x:Name="ZIndexItem1Text" Text="1" />
  <TextBox x:Name="ZIndexItem2Text" Text="2" />

  <StackPanel x:Name="ZIndexStackPanel">
    <Label VerticalAlignment="Top"
           Panel.ZIndex="{Binding Text, ElementName=ZIndexItem1Text}"
           Background="LightBlue" BorderBrush="Black" BorderThickness="1"
           Content="Item1" />
    <Label Margin="0,-15,0,0" VerticalAlignment="Top"
           Panel.ZIndex="{Binding Text, ElementName=ZIndexItem2Text}"
           Background="SkyBlue" BorderBrush="Black" BorderThickness="1"
           Content="Item2" />
  </StackPanel>
</StackPanel>

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

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

このページの挙動の記述は、すべて .NET 10 / Windows 11 で実際に動かして確かめたものです。計測には、このサイトのスクリーンショット生成ツールの StackPanelDemoScene を使いました。パネルは Measure と Arrange でレイアウトし、上にある要素は指定した位置のヒットテストで調べました。大きさは、計測したマシンでの値です。

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