Предотвратить пузыри события 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;
}
}
Вполне возможно, не самое лучшее решение, хотя.