2011-03-16 54 views
5

我想爲MenuItem實現鍵盤快捷鍵。我用下面的代碼:爲什麼設置MenuItem.InputGestureText在執行輸入手勢時會導致MenuItem激活?

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

但是,當我按下CTRL+NInputGestureText財產沒有響應。我正在使用Visual Studio Express Edition 2010.我在這裏丟失了什麼?

回答

9

這是該屬性的文檔中十分明瞭:

此屬性不與菜單項 輸入手勢相關聯;它 只是添加文本到菜單項。 應用程序必須處理用戶的 輸入以執行該操作。對於 有關如何將 命令與菜單項關聯的信息,請參閱 Command

4

要做到這一點,最好的辦法是讓一個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) 
{ 
    ... 
} 

如果你真的只想要一個「新建」命令,就可以跳過創建RoutedCommandInputGesture,因爲該命令是爲已創建:

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

... 

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

... 

private void New_Executed(object sender, ExecutedRoutedEventArgs e) 
{ 
    ... 
} 
2

一個解決方案,不涉及的命令和綁定是覆蓋所屬窗口的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; 
     } 
    } 
相關問題