C#のWPFでメニューを作成する

WPFでメニューを作成する方法について解説します。

 

<Menu>要素と<MenuItem>要素

XAMLでメニューを作成するには<Menu>要素を使用します。

<Menu>要素の中に<MenuItem>要素を配置する事で各メニュー項目を作成していきます。

<MenuItem>要素はその中に更に<MenuItem>要素を追加してメニューを階層構造にする事も可能です。

 

 

<Menu>要素は他のコントロールと同様に自由な位置に配置できますが、多くの場合はウィンドウ上部に配置する事になると思います。<DockPanel>要素などで配置しましょう。

<Window x:Class="WpfTest1.TestWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfTest1"
        mc:Ignorable="d"
        Title="TestWindow" Height="300" Width="300">
    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="メニュー1(_A)">
                <MenuItem Header="メニュー 1-1"/>
                <MenuItem Header="メニュー 1-2"/>
                <MenuItem Header="メニュー 1-3">
                    <MenuItem Header="メニュー 1-3-1"/>
                    <MenuItem Header="メニュー 1-3-2"/>
                </MenuItem>
            </MenuItem>
            <MenuItem Header="メニュー2(_B)"/>
        </Menu>
        <StackPanel>
        </StackPanel>
    </DockPanel>
</Window>

メニューを選択された時の動作は Click イベントを使って実装します。

セパレータを追加する

よく見るメニューでは、項目の間に区切り線が入れられて見やすくレイアウトされています。

WPFのメニューでも簡単に区切り線を追加する事が出来ます。

 

区切り線を入れたい場所に<Separator/>要素を追加しましょう。

<Menu DockPanel.Dock="Top">
    <MenuItem Header="メニュー1(_A)">
        <MenuItem Header="メニュー 1-1"/>
        <MenuItem Header="メニュー 1-2"/>
        <Separator/>
        <MenuItem Header="メニュー 1-3">
            <MenuItem Header="メニュー 1-3-1"/>
            <MenuItem Header="メニュー 1-3-2"/>
        </MenuItem>
    </MenuItem>
    <MenuItem Header="メニュー2(_B)"/>
</Menu>

メニュー項目の動作の実装(クリックイベント編)

メニューの項目を選択された場合の動作の実装はクリックイベントを使う方法をコマンドを使う方法があります。

クリックイベントを使う場合は、<MenuItem>要素の Click イベントを実装します。

<MenuItem Header="メニュー 1-1"  Click="Button_Click"/>
private void Button_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Menu 1-1");
}

メニュー項目の動作の実装(コマンド編)

メニューの項目を選択された場合の動作の実装はクリックイベントを使う方法をコマンドを使う方法があります。

コマンドを使う場合は、<MenuItem>要素の Command プロパティに ICommandオブジェクトをバインドします。

public class TestCommand : ICommand
{
    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        MessageBox.Show("TestCommand!");
    }
}

まず、ICommandインターフェースを実装したクラスを作ります。

Executeメソッドに動作する機能を記述していきます。

public partial class TestWindow : Window
{
    public TestCommand TestCmd { get; set; }


    public TestWindow()
    {
        InitializeComponent();

        TestCmd = new TestCommand();
        DataContext = this;
    }
}

CommandオブジェクトをWindowクラスで作成し、バインドできるよう DataContext プロパティをセットします。

<MenuItem Header="メニュー 1-2" Command="{Binding TestCmd}"/>

<MenuItem>要素の Command プロパティにバインドします。

アクセラレータキーを設定する

通常ではAltキーが押されるとメニューにフォーカスが移動するようになっています。

この時、特定のキーをが押されるとメニューがクリックされたのと同じ動作をさせる事が出来るようになっていて、マウスを使わずキーボード操作だけでメニューの選択が可能です。

これがアクセラレータキーという機能です。

 

各メニュー項目にキーを割り当ては Header プロパティの文字列で行います。

「_」(アンダーバー)の後の文字がアクセラレータキーとして割り当てられます。

※「_」アクセラレータキーとして解釈され表示されなくなるので注意しましょう

    <MenuItem Header="メニュー1(_A)">

ショートカットキーを設定する

ショートカットキーは特定のコマンドをキー操作で実行させるものです。

 

<MenuItem Header="メニュー 1-2" Command="{Binding TestCmd}" InputGestureText="Ctrl+A"/>

<MenuItem>要素には InputGestureText というプロパティがあります。

InputGestureText プロパティにキー操作の説明を記述します。

但し、このプロパティはメニューにテキストを表示するだけのもので、実際にコマンドを呼び出す部分は別になります。

<Window x:Class="WpfTest1.TestWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfTest1"
        mc:Ignorable="d"
        Title="TestWindow" Height="300" Width="300">
    <Window.InputBindings>
        <KeyBinding Command="{Binding TestCmd}" Gesture="Ctrl+A"/>
    </Window.InputBindings>
</Window>

ショートカットキーの操作に合わせてコマンドを実行するには InputBindings プロパティで行います。

<KeyBinding>の Gesture プロパティに割り当てるキーを設定し、Command プロパティに実行するコマンドをバインドします。