Переопределить клавишу ввода, но сохранить поведение по умолчанию для других клавиш в сетке данных wpf

Меня действительно беспокоит, что нажатие клавиши ввода в Datagrid перемещает выделение на один элемент вниз, я бы хотел иметь возможность решать, что он делает в обычном событии нажатия клавиши.

Итак, я создал новый класс, который наследует DataGrid, переопределил событие OnKeyDown и использовал его в качестве моей таблицы данных.

Это создает совершенно новый набор проблем, поскольку мне, по-видимому, приходится переписывать все остальные нажатия клавиш (навигация по клавишам со стрелками, Shift + выбор клавиш со стрелками, pgup / pgdn и т. Д.). Я пытался взломать его, но мне кажется бессмысленным тратить время на переписывание того, что уже было написано, и, вероятно, лучше того, что я придумаю.

Итак, как я могу заставить клавишу ввода делать то, что я хочу, не вмешиваясь в другие привязки клавиш по умолчанию для сетки данных?

заранее спасибо


person Steinthor.palsson    schedule 12.04.2011    source источник
comment
не могли бы вы поделиться своим кодом. У меня такая же проблема   -  person Kishore Kumar    schedule 26.04.2012


Ответы (5)


Просто проверьте, введена ли нажатая клавиша, если нет, вызовите базовый обработчик событий для KeyDown (что-то вроде base.OnKeyDown(sender, args);)

person anthonyvd    schedule 12.04.2011
comment
Это именно то, что я искал. И теперь я знаю, для чего предназначено базовое ключевое слово: D Спасибо - person Steinthor.palsson; 13.04.2011

Вам нужно будет привязать обработчик PreviewKeyDown к Datagrid, а затем вручную проверить, равно ли значение ключа Key.Enter.

Если да, установите e.Handled = true.

person Robin Maben    schedule 12.04.2011
comment
Разве это не подавило бы нажатие клавиши и не заставило бы клавишу ввода ничего не делать? - person Steinthor.palsson; 13.04.2011
comment
Да, по крайней мере, в сетке данных. Разве это не желаемый эффект? - person Robin Maben; 13.04.2011
comment
Возможно, я не совсем понял, мне не нужно поведение клавиши ввода по умолчанию, но я все же хочу иметь возможность использовать его в событии KeyDown для запуска моих собственных функций. - person Steinthor.palsson; 13.04.2011

Намного более простая реализация. Идея состоит в том, чтобы зафиксировать событие нажатия клавиши и, если клавиша «Enter», решить, в каком направлении вы хотите двигаться.
FocusNavigationDirection имеет несколько свойств, на основе которых можно изменять фокус.

/// <summary>
/// On Enter Key, it tabs to into next cell.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void LiquidityInstrumentViewsGrid_OnPreviewKeyDown(object sender, KeyEventArgs e)
{
    var uiElement = e.OriginalSource as UIElement;
    if (e.Key == Key.Enter && uiElement != null)
    {
        e.Handled = true;
        uiElement.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
    }
}
person Hunter    schedule 11.03.2014

Если он работает аналогично winforms, для нажатий клавиш, которые вы не обрабатываете, отметьте обработанное как false, и оно передаст нажатие клавиши. Класс KeyEventArgs

Handled Возвращает или задает значение, которое указывает текущее состояние обработки события для перенаправленного события при его прохождении по маршруту. (Унаследовано от RoutedEventArgs.)

person mservidio    schedule 12.04.2011

PreviewKeyDown с Handled = true - это плохое решение. Он перестанет обрабатывать Key на этапе туннелирования и никогда не всплывет в ключе. Проще говоря, он съел бы любое нажатие клавиши Enter. Это означало, что верхние панели никогда не получат событие KeyDown (представьте, что ваше Окно что-то принимает при ENTER _4 _...).

Правильное решение - это то, что предложил Энтони: оставить Handled = false, чтобы он продолжал пузыриться, и пропустить обработку Enter внутри DataGrid

public class DataGridWithUnhandledReturn : DataGrid
{
    /// <inheritdoc/>
    protected override void OnKeyDown(KeyEventArgs e)
    {
        if (e.Key == Key.Return && e.KeyboardDevice.Modifiers == ModifierKeys.None)
        {
            return;
        }

        base.OnKeyDown(e);
    }
}
person epox    schedule 01.02.2016