Горячие клавиши и UserControl

348
06 июля 2017, 00:01

Есть UserControl, в котором, помимо прочего, есть DataGrid.

Нужно извне привязать команду на Enter так:

 <myControls:ProductsDataGrid.InputBindings>
    <KeyBinding Key="Enter"
                Command="{Binding OpenProductCommand}"
                CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type myControls:ProductsDataGrid}}, Path=SelectedItem}" />
</myControls:ProductsDataGrid.InputBindings>

Проблема в том, что DataGridобрабатывает нажатие Enter по-своему и просто сдвигает выделение с текущей строки на следующую.

Если сменить клавишу, то все работает как надо.

Как добиться нужного поведения?

Если в DataGrid биндить хоткеи таким образом, то все работает, но решение ненадежное.

<DataGrid.InputBindings>
    <KeyBinding Key="Enter"
                Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ProductsDataGrid}}, Path=InputBindings[0].Command}"
                CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ProductsDataGrid}}, Path=InputBindings[0].CommandParameter}" />         
</DataGrid.InputBindings>
Answer 1

На самом деле решить указанную проблему можно по-разному, одно из решений будет заключаться в следующем:

В DataGrid, который расположен в вашем UserControl подписываемся на событие PreviewKeyDown. Далее, в обработчике этого события, генерируем событие нажатия на клавишу Enter.

private void OnPreviewKeyDown(object sender, KeyEventArgs e)
{
    // Если была нажата клавиша Enter. 
    if (e.Key == Key.Enter)
    {
         // Целевой элемент, который генерирует событие, ваш UserControl.
         var target = this;                 
         // Тип события.
         var routedEvent = Keyboard.KeyDownEvent;
         // Входной источник.
         var visual = PresentationSource.FromVisual(target);
         if (visual != null)
         {
             // Бросаем событие.
             target.RaiseEvent(
                 new KeyEventArgs(
                      Keyboard.PrimaryDevice,
                      visual, 0, e.Key)
             { RoutedEvent = routedEvent });
             // Помечаем, что пойманное DataGrid событие обработано.
             e.Handled = true;
          }
     }
}

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

Answer 2

Сталкивался с подобной проблемой. Использовал для реешния PreviewKeyDown - определял свою логику и выключал дальнейшее наступление события KeyDown.

XAML:

PreviewKeyDown="Window_PreviewKeyDown"

С#:

private void Window_PreviewKeyDown(Object sender, KeyEventArgs e)
{
    // логика
    e.Handled = false;
}

Наверное, можно и для MVVM данный подход использовать.

READ ALSO
progressbar при загрузке документа из БД. C#, DevExpress

progressbar при загрузке документа из БД. C#, DevExpress

Как настроить progressbar, чтобы отображал загрузку документ из БДДокумент вытягиваю запросом

248
Нарисовать Button при клике на окно WPF

Нарисовать Button при клике на окно WPF

Я хочу сделать приложение : юзер кликает и зажимает мышку, а когда он её отпускает, рисуется Button у которого левый верхний угол это координаты...

250