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

Expander Display

Expander は、見出しを常に表示し、見出しのクリックで内容を表示したり隠したりするコントロールです。

折りたたんだ内容にかかる負担

Expander は HeaderedContentControl を継承しています。Content が表示したり隠したりする内容で、折りたたんだ内容の負担は、思われているより小さいものです。最初から折りたたんだ Expander では、内容の要素は作られて Loaded も発生しましたが、測られませんでした。中に置いた 1000 項目の ListBox は ListBoxItem を 1 つも作りませんでした。この構成では、内容の要素そのものは作られて読み込まれましたが、一覧の項目のコンテナーは、展開するまで作られも測られもしませんでした。展開すると内容が測られ、ListBox は 11 個の項目を作り、内容にはもう一度 Loaded が発生しました。内容の Loaded で重い処理を始めてはいけません。折りたたんでいる間にも動き、展開したときにもう一度動きます。

開閉にアニメーションはない

IsExpanded は内容を表示するかどうかで、既定値は False です。既定で TwoWay にバインドされるので、バインドしたビューモデルのプロパティは利用者のクリックに追従します。デモアプリは Mode を指定せずにチェックボックスにバインドしているので、両者は連動します。実際のマウスで見出しをクリックすると、Expander が開き、チェックボックスにチェックが付き、Expanded が発生しました。チェックを外すと閉じて、Collapsed が発生しました。

既定のテンプレートの見出しは、HeaderSite という名前の ToggleButton です。テンプレートには表示状態のグループ(VisualStateGroup)もアニメーションもなく、IsExpanded・ExpandDirection・IsEnabled のトリガーで切り替えています。IsExpanded を False にすると、内容はその場で Collapsed になりました。アニメーションを付けるなら独自のテンプレートにします。

条件 計測値
基底クラス / IsExpanded の既定値、既定で双方向か / ExpandDirection HeaderedContentControl / False, True / Down
既定のテンプレート: 見出しの要素 / VisualStateGroups ToggleButton(名前 HeaderSite) / 0
トリガー IsExpanded=True; ExpandDirection=Right, Up, Left; IsEnabled=False
IsExpanded を False に: 内容の Visibility(直後 / 50 ms 後) Collapsed / Collapsed
見出しを実際にマウスでクリック: IsExpanded / バインドした CheckBox / イベント True / True / Expanded
続けて CheckBox を外す: IsExpanded / イベント False / Collapsed
折りたたみ中: 子の Loaded / 測定の回数 / 1000 項目の ListBox で作られた項目の数 1 / 0 / 0
展開した後 2 / 1 / 11

テンプレート、クリック、折りたたんだ内容。.NET 10 / Windows 11 で計測。

見出しと内容の配置

ExpandDirection は、見出しに対して内容をどちらに出すかで、既定値は Down です。80 × 40 の内容で試すと、Down では見出しが上、内容がその下に、Up では内容が見出しの上に来ました。Left と Right では、見出しは内容の横の幅 49、高さ 39 の列になり、文字は横書きのまま列の下の方に置かれました。内容は Left で左、Right で右でした。

読み取り専用の HasHeader は、Header があるかどうかを表します。Header が null のとき HasHeader は False でしたが、矢印の付いた見出しの ToggleButton は高さ 19 で表示されたままでした。消すには独自のテンプレートが必要です。

内容だけでなく見出しにも届くプロパティ

Expander に設定した Control のプロパティは、内容だけでなく見出しにも効きます。

条件 計測値
ExpandDirection=Down: 見出し / 内容 / 見出しの文字 x=2 y=2 w=116 h=19 / x=20 y=22 w=80 h=40 / x=25 y=3.52 w=49.04 h=15.96
ExpandDirection=Up: 見出し / 内容 / 見出しの文字 x=2 y=42 w=116 h=19 / x=20 y=1 w=80 h=40 / x=25 y=43.52 w=49.04 h=15.96
ExpandDirection=Left: 見出し / 内容 / 見出しの文字 x=82 y=2 w=49.04 h=38.96 / x=1 y=1.48 w=80 h=40 / x=82 y=25 w=49.04 h=15.96
ExpandDirection=Right: 見出し / 内容 / 見出しの文字 x=2 y=2 w=49.04 h=38.96 / x=52.04 y=1.48 w=80 h=40 / x=2 y=25 w=49.04 h=15.96
Header=null: HasHeader / 見出しの ToggleButton の Visibility、大きさ False / Visible, 196 x 19
FontWeight=Bold、Foreground=Red: 見出しの文字 / 内容の文字 Bold, #FFFF0000 / Bold, #FFFF0000
Background: 塗られる範囲 / 見出し / 内容(範囲の中か) x=0 y=0 w=200 h=38.96 / x=2 y=2 w=196 h=19 / x=1 y=22 w=198 h=15.96 (True)
Padding=0、BorderThickness=0: 見出し / 内容 x=1 y=1 w=198 h=19 / x=60 y=21 w=80 h=40
Padding=20、BorderThickness=0: 見出し / 内容 x=1 y=1 w=198 h=59 / x=60 y=81 w=80 h=40
Padding=0、BorderThickness=5: 見出し / 内容 x=6 y=6 w=188 h=19 / x=60 y=26 w=80 h=40

ExpandDirection、見出し、Control のプロパティ。.NET 10 / Windows 11 で計測。

デモアプリで試す

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

デモアプリの Expander のページには、ExpandDirection、IsExpanded、見出し、内容と、Control のプロパティ(Padding、フォントの各プロパティ、Background、Foreground、枠)の欄があります。見出しの欄は、空のテキストボックスを null に変換します。各欄の下の「Show Code」リンクで、その欄の XAML を表示できます。次の XAML は、IsExpanded の欄(ExpanderUsageControl.xaml)から、スタイルと周囲の GroupBox を省き、名前空間の宣言を加えたものです。

<StackPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <CheckBox x:Name="IsExpandedCheckBox" VerticalContentAlignment="Center" Content="IsExpanded" />

  <Expander x:Name="IsExpandedExpander"
            Content="CONTENT"
            Header="Expander"
            IsExpanded="{Binding IsChecked, ElementName=IsExpandedCheckBox}" />
</StackPanel>

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

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

このページの挙動の記述は、すべて .NET 10 / Windows 11 で実際に動かして確かめたものです。計測には、このサイトのスクリーンショット生成ツールの ExpanderDemoScene を使いました。見出しのクリックは、計測用のウィンドウの上で実際のマウスを使って行いました。位置は Expander の左上からのもので、大きさは計測したマシンでの値です。

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