WPF:OnKeyDown() не вызывается для клавиши пробела в элементе управления, производном от текстового поля WPF
Вопрос
В приложении WPF у меня есть элемент управления, который я извлек из текстового поля следующим образом:
public class SelectableTextBlock : TextBox
{
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
e.Handled = false;
}
}
Метод OnKeyDown не вызывается ни при вводе пробела в текстовое поле, ни при нажатии кнопки Backspace, но срабатывает для других входных данных, включая обычные печатные символы (например'a') и клавиши-модификаторы (например,).
Я использую этот элемент управления с IsReadOnly, установленным в значение true, чтобы я мог отображать выбираемый, неотредактируемый текст.Элемент управления, используемый в DataGrid от WPFToolkit, и я хочу, чтобы события KeyDown распространялись вверх по таблице данных, даже если SelectableTextBlock имеет фокус, поэтому я использую пользовательский элемент управления, чтобы явно пометить событие как необработанное.
Проблема в том, что событие даже не попадает под мой контроль для определенных ключей.Я не могу просто использовать OnPreviewKeyDown в DataGrid, чтобы обойти это, поскольку я хочу, чтобы другие элементы управления, используемые в data grid, проглатывали событие space KeyDown.
Кто-нибудь знает, как я могу заставить событие KeyDown для клавиши space распространяться вверх?
Спасибо.
Решение 2
Похоже, проблема в том, что событие нажатия клавиши space (и backspace и т.д.) Уже обрабатывается внутри текстового поля, прежде чем оно всплывет в моем производном элементе управления.Я предполагаю, что это часть процесса составления текста, как опубликовал Вим.
Чтобы обойти это, я добавил обработчик, который будет получать событие key down, даже если оно уже было обработано, и устанавливает для его обработанного элемента значение false, чтобы позволить ему нормально работать.В приведенном ниже примере он просто делает это для пробелов, но в моем случае мне нужно заставить его делать это для любых ключевых событий, которые я действительно не хочу, чтобы это обрабатывалось в моем SelectedableTextBlock, так как я еще не знаю, какие ключевые события могут заинтересовать родителей.
public class SelectableTextBlock : TextBox
{
public SelectableTextBlock() : base()
{
this.AddHandler(SelectableTextBlock.KeyDownEvent, new RoutedEventHandler(HandleHandledKeyDown), true);
}
public void HandleHandledKeyDown(object sender, RoutedEventArgs e)
{
KeyEventArgs ke = e as KeyEventArgs;
if (ke.Key == Key.Space)
{
ke.Handled = false;
}
}
...
}
Мне, конечно, все еще интересно, есть ли у кого-нибудь лучшее решение...
Спасибо, Э.
Другие советы
Событие PreviewKeyDown существует именно для такого рода вещей.
private void spacebarHandler_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space)
e.Handled = true;
}
Ваш обработчик KeyDown никогда не получит событие KeyDown для пробела.
Однажды у меня была эта проблема с пробелами и событиями в текстовом поле.РАЗВЕ события НЕ запускаются только при добавлении или удалении символа пробела?
Это то, что я получил в качестве ответа:(http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/446ec083-04c8-43f2-89dc-1e2521a31f6b)
Поскольку некоторые IME будут обрабатывать нажатие клавиши с пробелами как часть процесса составления текста, вот почему Avalon использует сообщение о правильном составленном тексте через событие TextInput.
Я мог бы полностью выйти за рамки, но чтение этой темы, безусловно, заставило меня задуматься о той проблеме, которая у меня когда-то была.
С уважением, Вим
Извлеките, скажем, RestrictKeysTextBox из TextBox .
public class RestrictKeysTextBox : TextBox
{
....
}
Переопределите событие OnPreviewKeyDown в RestrictKeysTextBox.
Поместите логику в это переопределение следующим образом:
if (e.Key == Key.Space)
{
e.Handled = true;
}
Привяжите экземпляр RestrictKeysTextBox к вашей сетке данных.
Это должно работать без переопределения OnPreviewKeyDown в DataGrid и устранять связанные с этим проблемы.