2011年7月18日月曜日

wpf RoutedUICommandのショートカットキーを変更した後、メニューの表示に反映させる

前回に続き、WPFでコンテキストメニューを使ったプログラムを組んでたときのお話。 MenuItemにRoutedUICommandを登録してショートカットキーを使えるようにしていました。 で、アプリケーション実行中にRoutedUICommandのInputGesturesを設定してショートカットキーを変更しました。 「それでコンテキストメニューのショートカットキーの表示も更新されるかな?」と思ったら反映されず。

色々試したところ、MenuItem.Commandに1度nullを設定し、変更後のRoutedUICommandを設定しなおすと反映されました。 完全に一時しのぎなやり方ですね。 まぁとりあえず、コンテキストメニュー全体の表示は次のようなコードで更新できました。

private void UpdateMenuItem(ItemCollection items)
{
    if (items == null)
        return;

    foreach (object item in items)
    {
        // MenuItem以外をスキップ
        if (item is MenuItem)
        {
            MenuItem menu = (MenuItem)item;

            if (menu.Command != null && menu.Command is RoutedUICommand)
            {
                RoutedUICommand command = (RoutedUICommand)menu.Command;

                // ショートカットキーの表示を更新するため、1時的にnullを代入
                menu.Command = null;

                // 1時的にnullにしていたのを戻す
                menu.Command = command;
            }

            UpdateMenuItem(menu.Items);
        }
    }
}

XAMLでこんなコードがあったとき

<ContextMenu Name="mainContextMenu">
    <MenuItem Header="★♭○...">
        ...
    </MenuItem>
</ContextMenu>

初期設定ファイルを読んだ後や設定ダイアログの終了後などにRoutedUICommandを全部更新し、その後

UpdateMenuItem(mainContextMenu.Items);

とすればメニューの表示も更新できます。

チラッとMSDNライブラリを読んだだけでは見つからなかったのでとりあえずこんなコードにしてしまったけど、もっと読んでいけば一発で更新するメソッドとかありそうですよね? まぁ、MSDNライブラリはチラッと読むだけで把握するには情報量が多すぎるので今はこんな感じで。

WPFの場合、「正しいコードを見つけたは良いけどそっちの方がコード量が多かった」みたいなこともありえるのがアレなところですよね。 これはそうじゃないといいけど...