Почему установка MenuItem.InputGestureText не вызывает активацию MenuItem при выполнении жеста ввода? - PullRequest
6 голосов
/ 16 марта 2011

Я хочу реализовать сочетания клавиш для MenuItem.Я использовал код ниже:

<MenuItem Header="_New" InputGestureText="CTRL+N" Click="NewMenu_Click">
    <MenuItem.Icon>
        <Image Source= "Images\NEW.PNG" Width="25" Height="28" />
    </MenuItem.Icon>
</MenuItem>`

Но свойство InputGestureText не отвечает, когда я нажимаю CTRL+N.Я использую Visual Studio Express Edition 2010. Я что-то здесь упускаю?

Ответы [ 3 ]

10 голосов
/ 16 марта 2011

Это явное указание в документации для свойства:

Это свойство не связывает жест ввода с элементом меню;он просто добавляет текст в пункт меню.Приложение должно обработать ввод пользователя для выполнения действия.Для получения информации о том, как связать команду с элементом меню, см. Команда .

4 голосов
/ 13 июля 2011

Лучший способ сделать это - создать Command и связать InputGesture с этой командой:

public static class Commands
{
    public static readonly RoutedCommand CreateNew = new RoutedCommand("New", typeof(Commands));

    static Commands()
    {
        SomeCommand.InputGestures.Add(new KeyGesture(Key.N, ModifierKeys.Control));
    }
}

...

// Wherever you want to create the MenuItem. "local" should be the namespace that
// you delcared "Commands" in.
<MenuItem Header="_New" Command="{x:Static local:Commands.CreateNew}">

...

// Wherever you want to process the command. I am assuming you want to do it in your 
// main window, but you can do it anywhere in the route between your main window and 
// the menu item.
<Window.CommandBindings>
    <CommandBinding Command="{x:Static local:Commands.CreateNew}"> Executed="CreateNew_Executed" />
</Window.CommandBindings>

...

// In the code behind for your main window (or whichever file you put the above XAML in)
private void CreateNew(object sender, ExecutedRoutedEventArgs e)
{
    ...
}

Если вам действительно нужна команда «New», вы можете пропустить создание RoutedCommand и InputGesture, потому что эта команда уже создана для вас:

<MenuItem Header="_New" Command="New">

...

<Window.CommandBindings>
    <CommandBinding Command="New" Executed="New_Executed" />
</Window.CommandBindings>

...

private void New_Executed(object sender, ExecutedRoutedEventArgs e)
{
    ...
}
2 голосов
/ 14 мая 2014

Одним из решений, которое не включает команды и привязки, является переопределение метода OnKeyDown собственного окна и поиск пункта меню с KeyGesture, соответствующим событию клавиатуры.

Вот коддля переопределения OnKeyDown окна:

protected override void OnKeyDown(KeyEventArgs e)
{
    base.OnKeyDown(e);

    // here I suppose the window's menu is named "MainMenu"
    MainMenu.RaiseMenuItemClickOnKeyGesture(e);
}

А вот код утилиты, который соответствует пункту меню с событием клавиатуры:

    public static void RaiseMenuItemClickOnKeyGesture(this ItemsControl control, KeyEventArgs args) => RaiseMenuItemClickOnKeyGesture(control, args, true);
    public static void RaiseMenuItemClickOnKeyGesture(this ItemsControl control, KeyEventArgs args, bool throwOnError)
    {
        if (args == null)
            throw new ArgumentNullException(nameof(args));

        if (control == null)
            return;

        var kgc = new KeyGestureConverter();
        foreach (var item in control.Items.OfType<MenuItem>())
        {
            if (!string.IsNullOrWhiteSpace(item.InputGestureText))
            {
                KeyGesture gesture = null;
                if (throwOnError)
                {
                    gesture = kgc.ConvertFrom(item.InputGestureText) as KeyGesture;
                }
                else
                {
                    try
                    {
                        gesture = kgc.ConvertFrom(item.InputGestureText) as KeyGesture;
                    }
                    catch
                    {
                    }
                }

                if (gesture != null && gesture.Matches(null, args))
                {
                    item.RaiseEvent(new RoutedEventArgs(MenuItem.ClickEvent));
                    args.Handled = true;
                    return;
                }
            }

            RaiseMenuItemClickOnKeyGesture(item, args, throwOnError);
            if (args.Handled)
                return;
        }
    }
...