WPF:OnKeyDown() не вызывается для клавиши пробела в элементе управления, производном от текстового поля WPF

StackOverflow https://stackoverflow.com/questions/1458748

  •  12-09-2019
  •  | 
  •  

Вопрос

В приложении 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 и устранять связанные с этим проблемы.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top