2011-11-23 96 views
3

我有一个非常简单的应用程序,我尝试将键盘快捷键绑定到绑定到菜单项的WPF命令。应用程序本身只包含一个MenuWebBrowser控件。InputBinding和WebBrowser控件

当我在WebBrowser之内时,键盘快捷键不会被路由到WPF菜单。例如,在Web浏览器中关注时键入“Ctrl + O”会显示IE打开页面。此外,在这个应用程序中,除非我的菜单集中(通过键入Alt),输入绑定不会触发。例如,我不能通过单击标题栏来关注WPF窗口,然后键入快捷方式。完整的代码被复制如下:

MainWindow.xaml

<Window x:Class="TestInputBindingsOnMenu.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="600" Width="800"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="*" /> 
     </Grid.RowDefinitions> 
     <Menu IsMainMenu="True" x:Name="_mainMenu" Grid.Row="0" /> 
     <WebBrowser Source="http://google.com" Grid.Row="1" /> 
    </Grid> 
</Window> 

MainWindow.xaml.cs

using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Input; 

namespace TestInputBindingsOnMenu 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      Initialize(); 
     } 

     private void Initialize() 
     { 
      MenuItem fileMenu = new MenuItem(); 
      MenuItem fileNew = new MenuItem(); 
      MenuItem fileOpen = new MenuItem(); 
      MenuItem fileExit = new MenuItem(); 

      fileMenu.Header = "File"; 
      fileNew.Header = "New"; 
      fileOpen.Header = "Open"; 
      fileExit.Header = "Exit"; 

      fileMenu.Items.Add(fileNew); 
      fileMenu.Items.Add(fileOpen); 
      fileMenu.Items.Add(fileExit); 

      _mainMenu.Items.Add(fileMenu); 

      var fileNewCommand = CreateCommand("New"); 
      var fileOpenCommand = CreateCommand("Open"); 
      var fileExitCommand = CreateCommand("Exit"); 

      _mainMenu.CommandBindings.Add(new CommandBinding(fileNewCommand, ExecuteNew)); 
      _mainMenu.CommandBindings.Add(new CommandBinding(fileOpenCommand, ExecuteOpen)); 
      _mainMenu.CommandBindings.Add(new CommandBinding(fileExitCommand, ExecuteExit)); 

      fileNew.Command = fileNewCommand; 
      fileOpen.Command = fileOpenCommand; 
      fileExit.Command = fileExitCommand; 

      _mainMenu.InputBindings.Add(new InputBinding(fileNewCommand, new KeyGesture(Key.N, ModifierKeys.Control))); 
      _mainMenu.InputBindings.Add(new InputBinding(fileOpenCommand, new KeyGesture(Key.O, ModifierKeys.Control))); 
      _mainMenu.InputBindings.Add(new InputBinding(fileExitCommand, new KeyGesture(Key.F4, ModifierKeys.Alt))); 
     } 

     private void ExecuteNew(object sender, ExecutedRoutedEventArgs e) 
     { 
      MessageBox.Show("New!!"); 
     } 

     private void ExecuteOpen(object sender, ExecutedRoutedEventArgs e) 
     { 
      MessageBox.Show("Open!!"); 
     } 

     private void ExecuteExit(object sender, ExecutedRoutedEventArgs e) 
     { 
      MessageBox.Show("Exit!!"); 
     } 

     private static RoutedCommand CreateCommand(string label) 
     { 
      return new RoutedCommand(label, typeof(MainWindow)); 
     } 
    } 
} 

回答

2

简单的解决方案

添加输入绑定WebBrowser控件以及主菜单:

Browser.InputBindings.Add(new KeyBinding(ApplicationCommands.Open, 
new KeyGesture(Key.O, ModifierKeys.Control))); 

硬解

这到底是怎么发生的是,UIElement是使用KeyDown事件,而要使用PreviewKeyDown事件,或添加处理程序,也负责处理Handled路由事件。如果你不知道这个,请查阅Tunnelling and Bubbling

由于这是在UIElement类中处理的,我建议在这种情况下使用不同的模式。 The MVVM Light framework提供EventToCommand行为。如果您可以将窗口的PreviewKeyDown事件路由到正确的命令,而不是使用KeyBindingInputBindings集合UIElement,您将得到您的解决方案。

您将需要一些自定义代码来检查哪个键被按下以及路由应该使用哪个命令。

+0

这主要是我想要的,除非焦点不在浏览器或菜单上。我尝试添加命令绑定到MainWindow,但也没有帮助。在上面的示例中(例如,在向浏览器控件添加绑定之后),如果我键入其中一个命令(弹出一个消息框),然后单击enter,我将不能再执行任何更多快捷方式,直到单击在浏览器内再次控制。 – sohum

+0

尝试将它们添加到浏览器和主窗口! – Bas

+0

我确实将它们添加到浏览器和主窗口以及菜单中。 – sohum