InputBinding и элемент управления WebBrowser

У меня есть очень простое приложение, в котором я пытаюсь связать сочетания клавиш с командой WPF, привязанной к пункту меню. Само приложение состоит только из элементов управления Menu и WebBrowser.

Когда я нахожусь в WebBrowser, сочетания клавиш не направляются в меню WPF. Например, при нажатии 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));
        }
    }
}

person sohum    schedule 23.11.2011    source источник


Ответы (1)


Простое решение

Добавьте привязки ввода в элемент управления WebBrowser, а также в главное меню:

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

Трудное решение

Здесь происходит следующее: UIElement использует событие KeyDown, а вы хотите использовать событие PreviewKeyDown или добавить обработчик, который также обрабатывает Handled перенаправленные события. Посмотрите Tunneling and Bubbling, если вы не знаете об этом. .

Поскольку это обрабатывается в классе UIElement, я бы посоветовал использовать в этой ситуации другой шаблон. Среда MVVM Light обеспечивает EventToCommand поведение. Если вы можете перенаправить событие PreviewKeyDown окна на нужные команды вместо использования KeyBinding с коллекцией InputBindings UIElement, у вас будет свое решение.

Вам понадобится некоторый пользовательский код, чтобы проверить, какая клавиша была нажата и к какой команде должна быть маршрутизация.

person Bas    schedule 28.11.2011
comment
Это сделало в основном то, что я хотел, за исключением того, что фокус не на браузере или меню. Я попытался добавить привязку команды к MainWindow, но это тоже не помогло. В приведенном выше примере, например (после добавления привязок к элементу управления браузера), если я ввожу одну из команд (которая выводит окно сообщения), а затем нажимаю ввод, я больше не могу выполнять какие-либо ярлыки, пока не нажму снова в пределах контроля браузера. - person sohum; 30.11.2011
comment
Попробуйте добавить их и в браузер, и в главное окно! - person Bas; 30.11.2011
comment
Я добавил их в браузер и главное окно, а также в меню. - person sohum; 30.11.2011