WPF: OnKeyDown() не вызывается для пробела в управлении, полученном из WPF TextBox
В приложении WPF у меня есть элемент управления, который я получил из TextBox следующим образом:
public class SelectableTextBlock : TextBox
{
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
e.Handled = false;
}
}
Метод OnKeyDown не вызывается при вводе пробела в TextBox и при нажатии Backspace, но срабатывает для другого ввода, включая обычные печатные символы (например, "a" ) и клавиши-модификаторы (например,).
Я использую этот элемент управления с IsReadOnly, установленным в true, чтобы я мог отображать выбираемый, неизменяемый текст. Элемент управления, используемый в WPFoolkit DataGrid, и я хочу, чтобы события KeyDown распространялись по сетке данных, даже если в SelectableTextBlock есть фокус, поэтому я использую настраиваемый элемент управления, чтобы явно отмечать событие как необработанное.
Проблема в том, что это событие даже не позволяет мне управлять некоторыми ключами. Я не могу просто использовать OnPreviewKeyDown в DataGrid, чтобы обойти это, так как я хочу, чтобы другие элементы управления, используемые в сетке данных, проглотили пробел KeyDown.
Кто-нибудь знает, как я могу получить событие KeyDown для распространения пробела?
Спасибо.
Ответы
Ответ 1
Похоже, проблема заключается в том, что событие key (и backspace и т.д.) с ключевыми словами обрабатывается уже внутри TextBox, прежде чем оно превратится в мой производный элемент управления. Я предполагаю, что это часть процесса составления текста, как опубликовал Wim.
Чтобы обойти это, я добавил обработчик, который получит событие с нажатием клавиши, даже если оно уже обработано, и устанавливает его обработанный элемент равным 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;
}
}
...
}
Мне, конечно, все равно интересно, есть ли у кого-то лучшее решение...
Спасибо,
Е.
Ответ 2
Событие PreviewKeyDown существует именно для такого рода вещей.
private void spacebarHandler_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space)
e.Handled = true;
}
Ваш обработчик KeyDown никогда не получит событие KeyDown для пробела.
Ответ 3
У меня была проблема с пробелами и событиями один раз в текстовом поле. Не активируются ли события НЕ только при добавлении или удалении символа пробела?
Вот что я получил в качестве ответа: (http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/446ec083-04c8-43f2-89dc-1e2521a31f6b)
Поскольку некоторые IME будут обрабатывать пробельные нажатия клавиш как часть процесса составления текста, то почему он ловит Avalon для сообщения правильного композитного текста через событие TextInput.
Я мог быть полностью вне сферы действия, но, читая эту нить, emmideatly заставил меня подумать об этой проблеме, которую я когда-то имел.
С уважением,
Wim
Ответ 4
Выведите слово: RestrictKeysTextBox из TextBox.
public class RestrictKeysTextBox : TextBox
{
....
}
Переопределить событие OnPreviewKeyDown в RestrictKeysTextBox.
Поместите логику в это переопределение следующим образом:
if (e.Key == Key.Space)
{
e.Handled = true;
}
Привяжите экземпляр RestrictKeysTextBox к вашему DataGrid.
Это должно работать без переопределения OnPreviewKeyDown в DataGrid и устранения связанных проблем.