WPF: OnKeyDown () не вызывается для пробела в элементе управления, полученном из WPF TextBox - PullRequest
16 голосов
/ 22 сентября 2009

В приложении WPF у меня есть элемент управления, полученный из TextBox, следующим образом:

public class SelectableTextBlock : TextBox
{
    protected override void OnKeyDown(KeyEventArgs e)
    {
        base.OnKeyDown(e);
        e.Handled = false;
    }
}

Метод OnKeyDown не вызывается при вводе пробела в TextBox и при нажатии клавиши Backspace, но запускается для другого ввода, включая обычные печатаемые символы (например, «a») и клавиши-модификаторы (например,).

Я использую этот элемент управления с IsReadOnly, установленным в true, чтобы я мог отображать выбираемый, не редактируемый текст. Элемент управления, используемый в DataGrid WPFToolkit, и я хочу, чтобы события KeyDown распространялись вверх по сетке данных, даже если у SelectableTextBlock есть фокус, поэтому я использую пользовательский элемент управления, чтобы явно пометить событие как необработанное.

Проблема в том, что событие даже не попадает под мой контроль определенных ключей. Я не могу просто использовать OnPreviewKeyDown в DataGrid, чтобы обойти это, так как я хочу, чтобы другие элементы управления, используемые в сетке данных, поглощали событие KeyDown пространства.

Кто-нибудь знает, как я могу получить событие KeyDown для распространения пробела?

Спасибо.

Ответы [ 4 ]

16 голосов
/ 13 июля 2013

Событие PreviewKeyDown существует именно для такого рода вещей.

private void spacebarHandler_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Space)
        e.Handled = true;
}

Ваш обработчик KeyDown никогда не получит событие KeyDown для пробела.

14 голосов
/ 23 сентября 2009

Кажется, проблема в том, что событие нажатия клавиши пробела (и возврата на задний план и т. Д.) Уже обрабатывается внутри TextBox, прежде чем оно всплывет до моего производного элемента управления. Я полагаю, как часть процесса создания текста, как написал Вим.

Чтобы обойти это, я добавил обработчик, который получит событие нажатия клавиши, даже если он уже был обработан, и установил для его члена Handled значение 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 голосов
/ 15 июня 2011

Получите право голоса, RestrictKeysTextBox из TextBox.

public class RestrictKeysTextBox : TextBox
{
    ....
}

Переопределить событие OnPreviewKeyDown в RestrictKeysTextBox.

Поместите логику в это переопределение так:

if (e.Key == Key.Space)
{
    e.Handled = true;
}

Свяжите экземпляр RestrictKeysTextBox с вашей сеткой данных.

Это должно работать без переопределения OnPreviewKeyDown в DataGrid и устранения связанных с этим проблем.

2 голосов
/ 22 сентября 2009

У меня была эта проблема с пробелами и событиями один раз в текстовом поле. События НЕ запускаются только при добавлении или удалении пробела?

Вот что я получил в ответ: (http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/446ec083-04c8-43f2-89dc-1e2521a31f6b)

Поскольку некоторые IME будут обрабатывать нажатие на пробельные символы как часть процесса составления текста, поэтому он использует Avalon для сообщения о правильном составном тексте через событие TextInput. Я мог бы быть полностью вне поля зрения, но чтение этой темы неизменно заставляло меня задуматься над тем вопросом, который у меня когда-то был.

С уважением, Wim

...