Предотвратить пузыри события KeyDown из TextBox в MainWindow в WPF

У меня есть программа, которая содержит текстовое поле управления. Пользователь может вводить текст в этот элемент управления. Пользователь также может нажимать определенные клавиши для запуска других действий (это обрабатывается в главном окне). У меня есть примеры кода XAML и C# для демонстрации моей установки.

XAML

<Window x:Class="RoutedEventBubbling.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>

        <TextBox Grid.Row="0" />
        <TextBox x:Name="Output" Grid.Row="1" IsReadOnly="True" />
    </Grid>
</Window>

C#

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

namespace RoutedEventBubbling
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private int mHitCount = 0;

        public MainWindow()
        {
            InitializeComponent();
        }

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

            this.Output.Text = string.Format("Hit Count: {0}", ++mHitCount);
        }
    }
}

Как вы, возможно, поняли, в случае этой программы, если я начну вводить в первый TextBox вторая будет обновлена ​​с количеством посещений. Это нежелательный результат, так как у меня могут быть определенные действия, которые я хочу вызвать при работе с MainWindow OnKeyDown метод.

Таким образом, мой вопрос заключается в следующем: можно ли предотвратить OnKeyDown метод, вызываемый в MainWindow, и в то же время позволяющий вводить текст в текстовое поле? Я знаю о e.Handled = true подход, но в этом случае делать это на KeyDown событие TextBox предотвратит ввод текста. Если это невозможно, мне придется найти другой способ справиться со всем этим.

Заранее спасибо.

РЕДАКТИРОВАТЬ

Я только что нашел способ решить эту проблему. Если я справлюсь с MainWindow OnTextInput вместо этого, то желаемый результат будет достигнут как TextInput событие TextBox будет обработан. Ниже приведен пример кода, который я использовал:

private Key mPressedKey;

protected override void OnKeyDown(KeyEventArgs e)
{
    // Note: This method will be called first.

    base.OnKeyDown(e);

    // Store the pressed key
    mPressedKey = e.Key;
}

protected override void OnTextInput(TextCompositionEventArgs e)
{
    // Note: This method will be called second, and only if the textbox hasn't handled it.

    base.OnTextInput(e);

    this.Output.Text = string.Format("Hit Count: {0}", ++mHitCount);

   // ... Handle pressed key ...
}

2 ответа

Решение

Я решил обойти эту проблему, используя следующую настройку:

private Key mPressedKey;

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

    mPressedKey = e.Key;
}

protected override void OnTextInput(TextCompositionEventArgs e)
{
    base.OnTextInput(e);

    // ... Handle mPressedKey here ...
}

protected override void OnMouseDown(MouseButtonEventArgs e)
{
    base.OnMouseDown(e);

    // Force focus back to main window
    FocusManager.SetFocusedElement(this, this);
}

Это было сделано в MainWindow.xaml.cs. Это что-то вроде хака, но это дало желаемый результат.

Вы могли бы установить защиту на основе типа для этого оператора:

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

    if (e.OriginalSource is TextBoxBase == false)
    {
        mPressedKey = e.Key;
    }
}

Вполне возможно, не самое лучшее решение, хотя.

Другие вопросы по тегам