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

Menu Menu

Menu は、見出しを並べたバーで、見出しごとにコマンドの一覧を開きます。各項目は MenuItem で、項目自身がサブメニューを持てます。

どのキーでメニューに入るか

Menu の IsMainMenu は、Alt を押したときにメニューへ入るかどうかで、既定値は True です。TextBox にフォーカスがある状態で実際に Alt を押すと、True では最初の見出しが強調されてフォーカスが移り、False では何も起きませんでした。既定値が True なので、Alt と F10 の通知を受ける必要のないほかの Menu には IsMainMenu="False" を設定します。

ドキュメントは IsMainMenu を Alt と F10 の通知を受けるかどうかと説明しています。日本語入力を使う計測したマシンでは、TextBox にフォーカスがある状態で実際に F10 を押すと、どちらでも何も起きませんでした。True で、Button にフォーカスがある状態の実際の F10 と、WPF の入力管理を通して TextBox に送った F10 では、どちらもメニューに入りました。違いの原因として、F10 を自分でも使う日本語入力が考えられますが、入力方式をオフにして測ってはいないので、確かめていません。

アクセスキーはどちらでも働き、Alt+M は False でもデモアプリの「Main Menu(_M)」を開きました。

項目の Role と見出しの状態

Menu は MenuItem を持ち、各 MenuItem の読み取り専用の Role は、置かれた位置と子の有無で決まります。デモアプリの Role の欄の 4 項目は、TopLevelHeader・SubmenuHeader・SubmenuItem・TopLevelItem でした。Role は子に応じて変わり、チェックできない TopLevelItem に子を追加すると TopLevelHeader になりました。WPF のソースでは、見出しの Role になるのは子を持ち、かつ IsCheckable が False の場合だけです。チェックできる項目に子を持たせた場合は測っていません。

見出しの状態は IsHighlighted・IsPressed・IsSubmenuOpen・IsSuspendingPopupAnimation で表され、IsSubmenuOpen 以外は読み取り専用です。実際のマウスを重ねると IsHighlighted が True になりました。ボタンを押すと IsPressed が True になってサブメニューが開き、離すと IsPressed だけが戻りました。IsSuspendingPopupAnimation は、サブメニューが開くと True になりました。見出しが 2 つあるとき、1 つ目を開いたまま 2 つ目にマウスを重ねると、1 つ目が閉じて 2 つ目が開きました。

チェックできる項目と、開いたままのサブメニュー

IsCheckable は、クリックで IsChecked を切り替えるかどうかで、既定値は False です。実際にクリックすると項目にチェックが付き、もう一度クリックすると外れました。IsCheckable でなければ、クリックしてもチェックは付きませんでした。IsChecked はチェックボックスと TwoWay でバインドでき、チェックボックスはクリックに追従し、コードでチェックボックスにチェックを付けると項目にもチェックが付きました。

チェックできる項目どうしは排他ではなく、同じサブメニューの 2 項目をクリックすると両方にチェックが付きました。排他の選択にするには、ほかの項目のチェックをコードで外すか、値のバインドで表します。

StaysOpenOnClick は、項目をクリックした後もサブメニューを開いたままにするかどうかで、既定値は False です。実際にクリックすると、False ではサブメニューが閉じ、True では開いたままでした。

コマンド、IsEnabled、ショートカットの文字

Command に ApplicationCommands.Copy を設定し、実際のクリックでメニューを開くと、TextBox で何も選択していなければ無効、全体を選択していれば有効、Button にフォーカスがあれば無効でした。メニューを開いている間、キーボードフォーカスは MenuItem にありましたが、項目は TextBox の選択に従いました。

サブメニューの項目の IsEnabled は、メニューが閉じている間は最新ではありません。TextBox にフォーカスがあり何も選択していないとき、Copy の項目の IsEnabled は、コマンドの CanExecute が False を返すのに True でした。実際のクリックでメニューを開くと、項目は無効になりました。項目の IsEnabled を読まず、コマンドの CanExecute を呼びます。

Icon は左に出す画像、InputGestureText は右に出すショートカットの文字です。InputGestureText は文字だけで、「Ctrl+O」は表示されましたが、実際に Ctrl+O を押しても項目はクリックされませんでした。キーの組み合わせを持つコマンドでは自動で入り、Copy の項目は設定しなくても Ctrl+C でした。ウィンドウに KeyBinding を付けると、キーの組み合わせを持たないコマンドが実際の Ctrl+O で実行されましたが、項目の InputGestureText は空のままでした。ショートカットは KeyBinding で結び、InputGestureText も設定します。

条件 計測値
既定値: IsMainMenu; IsCheckable, IsChecked, StaysOpenOnClick, InputGestureText True; False, False, False, (空)
デモの Role の欄: 4 つの項目 TopLevelHeader, SubmenuHeader, SubmenuItem, TopLevelItem
TopLevelItem に子を追加: その Role TopLevelHeader
IsCheckable True、StaysOpenOnClick True: 開いたか; クリック: チェック / CheckBox / 開いたままか; もう一度 True; True / True / True; False / True
コードで CheckBox をチェック: 項目の IsChecked True
IsCheckable True、StaysOpenOnClick False: 開いたか; クリック: チェック / CheckBox / 開いたままか; もう一度 True; True / True / False; -
IsCheckable False、StaysOpenOnClick True: 開いたか; クリック: チェック / CheckBox / 開いたままか; もう一度 True; False / False / True; False / True
チェックできる項目 2 つを両方クリック: IsChecked True, True
IsMainMenu True、実際に Alt: 強調表示 / サブメニューが開くか / TextBox がフォーカスを保つか True / False / False
IsMainMenu True、実際に F10: 強調表示 / サブメニューが開くか / TextBox がフォーカスを保つか False / False / True
IsMainMenu True、実際に Alt+M: 強調表示 / サブメニューが開くか / TextBox がフォーカスを保つか True / True / False
IsMainMenu False、実際に Alt: 強調表示 / サブメニューが開くか / TextBox がフォーカスを保つか False / False / True
IsMainMenu False、実際に F10: 強調表示 / サブメニューが開くか / TextBox がフォーカスを保つか False / False / True
IsMainMenu False、実際に Alt+M: 強調表示 / サブメニューが開くか / TextBox がフォーカスを保つか True / True / False
IsMainMenu True、実際に F10、Button にフォーカス: 強調表示 / 開くか / メニューにフォーカスがあるか True / False / True
IsMainMenu True、InputManager 経由で F10、TextBox にフォーカス: 強調表示 / 開くか / メニューにフォーカスがあるか True / False / True
InputGestureText "Ctrl+O": 表示されるか / Copy の項目の InputGestureText 表示される(幅 35.83) / Ctrl+C
TextBox にフォーカスがある状態で実際に Ctrl+O: Click の回数 0
Copy の項目、メニューは閉じたまま、TextBox にフォーカス、選択なし: IsEnabled / CanExecute True / False
実際のクリックで開く: 選択なし; 全選択(フォーカス); Button にフォーカス False; True (MenuItem); False
Observation Target: Highlighted / Pressed / SubmenuOpen / Suspending: 前; ホバー False / False / False / False; True / False / False / False
実際にボタンを押す; 離す True / True / True / True; True / False / True / True
File をクリック: 開くか / Suspending; Edit にホバー: File が開いているか; Edit が開くか / Suspending True / True; False; True / True
ウィンドウの KeyBinding Ctrl+O、実際に Ctrl+O: 実行されたか / 項目の InputGestureText 1 / (空)

Role、チェックできる項目、メインメニュー、ショートカット、コマンド、見出しの状態。.NET 10 / Windows 11 で計測。

デモアプリで試す

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

デモアプリの Menu のページには、IsMainMenu、IsCheckable と IsChecked・StaysOpenOnClick、Role、Command、Icon と InputGestureText の欄と、IsHighlighted・IsPressed・IsSubmenuOpen・IsSuspendingPopupAnimation を表示する最後の欄があります。IsCheckable の欄は IsCheckable と StaysOpenOnClick の両方を True で始め、チェックボックスを IsChecked に TwoWay でバインドしています。Command の欄は ApplicationCommands.Copy を使い、InputGestureText の欄は「Ctrl+O」を表示します。各欄の下の「Show Code」リンクで、その欄の XAML を表示できます。次の XAML は、IsCheckable の欄(MenuUsageControl.xaml)から、スタイルと周囲の GroupBox を省き、名前空間の宣言を加えたものです。

<StackPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <CheckBox x:Name="IsCheckableCheckBox" Content="IsCheckable" IsChecked="True" />
  <CheckBox x:Name="StaysOpenOnClickCheckBox" Content="StaysOpenOnClick" IsChecked="True" />

  <Menu IsMainMenu="False">
    <MenuItem Header="Options">
      <MenuItem x:Name="InteractiveMenuItem"
                Header="Interactive Item"
                IsCheckable="{Binding IsChecked, ElementName=IsCheckableCheckBox}"
                StaysOpenOnClick="{Binding IsChecked, ElementName=StaysOpenOnClickCheckBox}" />
    </MenuItem>
  </Menu>

  <CheckBox x:Name="IsCheckedSyncCheckBox"
            Content="IsChecked"
            IsChecked="{Binding IsChecked, ElementName=InteractiveMenuItem, Mode=TwoWay}" />
</StackPanel>

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

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

このページの挙動の記述は、すべて .NET 10 / Windows 11 で実際に動かして確かめたものです。計測には、このサイトのスクリーンショット生成ツールの MenuDemoScene を使い、デモアプリの各欄と同じ形のメニューで試しました。クリックとマウスの重ね合わせは実際のマウスで行い、Alt・F10・ショートカットは実際のキー入力として押しました。F10 は切り分けのため、WPF の入力管理を通しても送りました。計測したマシンのクリップボードを書き換えないよう、Copy の項目はクリックせず、有効かどうかだけを読みました。

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