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

ToolBar Menu

ToolBar はコマンドを帯状に並べ、入りきらない項目をオーバーフローのメニューへ移すコントロールです。複数のツールバーは ToolBarTray の中に並べられます。

オーバーフローに ToolBarTray は要らない

ToolBar は HeaderedItemsControl を継承しています。入りきらない項目は、右端のボタンで開くオーバーフローのポップアップへ移ります。これに ToolBarTray は要りません。幅 100 の ToolBar を単独で置くと、5 つのボタンのうち 4 つがオーバーフローへ移りました。

添付プロパティの ToolBar.OverflowMode は、幅が足りないときに項目をどこへ置くかで、既定値は AsNeeded です。5 つのボタンの 2 つ目を対象にすると、幅 100 では、AsNeeded でオーバーフローへ移り、Never ではツールバーに残り、Always では幅 400 でも常にオーバーフローにありました。Never はすべてを見せる方法ではありません。幅 100 のツールバーで 5 つのボタンをすべて Never にすると、オーバーフローへは何も移らず、ボタンは 198.15 の幅を取り、大半が切れて見えなくなりました。Never は少数の項目に絞ります。

HasOverflowItems はツールバーのオーバーフローに項目があるかどうかを、添付プロパティの ToolBar.IsOverflowItem は個々の項目がオーバーフローにあるかどうかを表し、どちらも読み取り専用です。IsOverflowOpen はオーバーフローのポップアップが開いているかどうかです。オーバーフローに何もないとき(幅 400)も、オーバーフローボタンは表示されたまま無効になっていました。この状態で IsOverflowOpen = true にすると、表示する項目のないポップアップが開きました。

ToolBar の幅 AsNeeded Never Always
100 オーバーフロー(5 個中 4 個がオーバーフロー) バー(5 個中 4 個がオーバーフロー) オーバーフロー(5 個中 4 個がオーバーフロー)
200 バー(5 個中 2 個がオーバーフロー) バー(5 個中 2 個がオーバーフロー) オーバーフロー(5 個中 1 個がオーバーフロー)
400 バー(5 個中 0 個がオーバーフロー) バー(5 個中 0 個がオーバーフロー) オーバーフロー(5 個中 1 個がオーバーフロー)

デモアプリのオーバーフローの欄の対象ボタンの行き先(ツールバーの幅と OverflowMode ごと)。.NET 10 / Windows 11 で計測。

ツールバーの中の項目に当たるスタイル

ToolBar に置いた項目には、ツールバー用のスタイルが当たります。Button・ToggleButton・ComboBox・Separator には、それぞれ ToolBar.ButtonStyleKey・ToggleButtonStyleKey・ComboBoxStyleKey・SeparatorStyleKey のスタイルが適用されていました。そのため ToolBar の中のボタンには、アプリ全体の暗黙の Button スタイルは使われません。項目の見た目はツールバー用のスタイルキーで変えます。横向きのツールバーの Separator は、幅 1 の縦線になりました。

ツールバー自体の Background は直接変えられます。LightYellow を設定すると、テンプレートの枠の既定の #FFEEF5FD が置き換わりました。

ToolBarTray が加えるもの:バンド、ドラッグ、ロック

Band は ToolBarTray のどのバンドに置くか、BandIndex はそのバンドの中での順番です。計測した横向きのトレイではバンドは行で、縦向きのトレイでは WPF のソースによれば列になります(こちらは測っていません)。バンドが 0・0・1・1、インデックスが 0・1・0・1 のツールバーは、(0, 0)・(147.79, 0)・(0, 30.96)・(147.79, 30.96) に置かれました。つまみでドラッグすると値が変わり、バンド 1・インデックス 0 のツールバーを右へ 250、上へ 30 ドラッグすると、バンド 0・インデックス 0 に移りました。利用者のレイアウトを復元するなら、Band と BandIndex を保存します。

トレイの IsLocked は中のツールバーに引き継がれます。True では各ツールバーのつまみが非表示(Collapsed)になり、ドラッグできなくなりました。レイアウトを固定するときに設定します。

トレイの Orientation がツールバーの向きを決めます。ToolBar.Orientation は読み取り専用で、縦向きのトレイでは Vertical、トレイの外では Horizontal になり、設定しようとすると InvalidOperationException が発生しました。2 つの向きが食い違うことはありません。

条件 計測値
ToolBar の中の Button / ToggleButton / ComboBox / Separator: スタイル ToolBar のスタイル / ToolBar のスタイル / ToolBar のスタイル / ToolBar のスタイル
横の ToolBar の中の Separator: 幅 / 高さ 1 / 17.96
Background 指定なし: 値(出どころ) / テンプレートの枠 #FFEEF5FD (DefaultStyle) / #FFEEF5FD
Background LightYellow: 値(出どころ) / テンプレートの枠 #FFFFFFE0 (Local) / #FFFFFFE0
トレイ、(Band, BandIndex) (0,0) (0,1) (1,0) (1,1): 位置 (0, 0) (147.79, 0) (0, 30.96) (147.79, 30.96)
(1,0) のつまみを (250, -30) ドラッグ: その Band / BandIndex 0 / 0
ToolBarTray IsLocked=False: ToolBar の IsLocked / つまみの Visibility False / Visible
ToolBarTray IsLocked=True: ToolBar の IsLocked / つまみの Visibility True / Collapsed
トレイが Vertical: ToolBar.Orientation(出どころ)/ トレイの外の ToolBar Vertical (Default) / Horizontal
ToolBar.Orientation を設定 InvalidOperationException

項目のスタイル、背景、バンド、ロック、向き。.NET 10 / Windows 11 で計測。

デモアプリで試す

デモアプリの ToolBar のページ。左にコントロールの一覧、右に最初の節の HasOverflowItems (ToolBar) / IsOverflowItem (ToolBar) / IsOverflowOpen (ToolBar) / OverflowMode (ToolBar)

デモアプリの ToolBar のページには、オーバーフローのプロパティ(OverflowMode、HasOverflowItems と IsOverflowItem、IsOverflowOpen)、Band と BandIndex、ToolBarTray の Background・IsLocked・Orientation の欄があります。オーバーフローの欄は、5 つのボタンを持つ幅 100〜400 の ToolBar を単独で置いて 2 つ目のボタンを対象にし、ツールバーと対象のボタンの HasOverflowItems と IsOverflowItem を表示し、IsOverflowOpen をチェックボックスにバインドしています。バンドの欄は、トレイに 4 つのツールバーを置いています。各欄の下の「Show Code」リンクで、その欄の XAML を表示できます。次の XAML は、オーバーフローの欄(ToolBarUsageControl.xaml)から、スタイル、周囲の GroupBox、一部の配置の属性を省き、名前空間の宣言を加えたものです。markupextensions はデモアプリ独自のマークアップ拡張の接頭辞です。

<StackPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:markupextensions="clr-namespace:WPFStandardControlDemoApp.Common.MarkupExtensions">
  <CheckBox x:Name="IsOverflowOpenCheckBox" Content="IsOverflowOpen" />
  <ComboBox x:Name="OverflowModeComboBox"
            DisplayMemberPath="Name"
            ItemsSource="{markupextensions:EnumBindingSource EnumType=OverflowMode}"
            SelectedValuePath="Value" SelectedIndex="0" />
  <Slider x:Name="WidthSlider" Minimum="100" Maximum="400" Value="200"
          LargeChange="50" TickFrequency="50" TickPlacement="BottomRight"
          AutoToolTipPlacement="BottomRight" />

  <ToolBar x:Name="OverflowToolBar" HorizontalAlignment="Left"
           Width="{Binding Value, ElementName=WidthSlider}"
           IsOverflowOpen="{Binding IsChecked, ElementName=IsOverflowOpenCheckBox}">
    <Button Content="Item 1" />
    <Button x:Name="OverflowTargetButton" Content="Target Item"
            ToolBar.OverflowMode="{Binding SelectedValue, ElementName=OverflowModeComboBox}" />
    <Button Content="Item 2" />
    <Button Content="Item 3" />
    <Button Content="Item 4" />
  </ToolBar>

  <TextBlock Text="{Binding HasOverflowItems, ElementName=OverflowToolBar}" />
  <TextBlock Text="{Binding (ToolBar.IsOverflowItem), ElementName=OverflowTargetButton}" />
</StackPanel>

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

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

このページの挙動の記述は、すべて .NET 10 / Windows 11 で実際に動かして確かめたものです。計測には、このサイトのスクリーンショット生成ツールの ToolBarDemoScene を使いました。ツールバーのドラッグは、マウスでドラッグしたときと同じ DragStarted・DragDelta・DragCompleted イベントをつまみに発生させて再現しました。大きさと位置は計測した環境での値です。

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