Почему ввод с клавиатуры не работает для ScrollViewer, когда дочерний элемент управления имеет фокус ввода? - PullRequest
1 голос
/ 10 июня 2010

Почему ввод с клавиатуры не работает для ScrollViewer, когда дочерний элемент управления имеет фокус ввода?

Это сценарий. Откроется окно WPF. Он устанавливает фокус на элемент управления, встроенный в ScrollViewer.

Я нажимаю клавиши вверх и вниз, влево и вправо. ScrollViewer, похоже, не обрабатывает ключевые события, кто-нибудь знает почему?

Это самый простой пример:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300"
    FocusManager.FocusedElement="{Binding ElementName=control}"
    >
    <Grid>
        <ScrollViewer
            HorizontalScrollBarVisibility="Auto"
           >
            <ItemsControl
                x:Name="control"
                Width="1000"
                Height="1000"
                />
        </ScrollViewer>        
    </Grid>
</Window>

Когда вы запускаете приложение, которое содержит это окно, появляется «элемент управления», который имеет фокус, как я и предполагал. Кажется, что нажатие клавиши приводит к тому, что всплывающие ключевые события достигают ScrollViewer (я проверял это с помощью WPF Snoop). Я не могу понять, почему он не отвечает на ввод.

Ответы [ 2 ]

7 голосов
/ 12 июня 2010

Проблема

ScrollViewer игнорирует все события KeyDown, для которых OriginalSource не является ScrollViewer.OriginalSource для KeyDown установлен на фокусированный элемент управления, поэтому ScrollViewer игнорирует его, когда у ребенка есть фокус.

Решение

Поймать событие KeyDown и вызватьего копия прямо в ScrollViewer, поэтому он будет иметь правильный OriginalSource, например:

void ScrollViewer_KeyDown(object sender, KeyEventArgs e)
{
  if(e.Handled) return;
  var temporaryEventArgs =
    new KeyEventArgs(e.KeyboardDevice, e.InputSource, e.Timestamp, e.Key)
    {
      RoutedEvent = e.RoutedEvent
    };
  // This line avoids it from resulting in a stackoverflowexception
  if (sender is ScrollViewer) return;
  ((ScrollViewer)sender).RaiseEvent(temporaryEventArgs);
  e.Handled = temporaryEventArgs.Handled;
}

, обработчик событий может быть добавлен в XAML:

<ScrollViewer KeyDown="ScrollViewer_KeyDown" />

или в коде:

scrollViewer.AddHandler(Keyboard.KeyDownEvent, ScrollViewer_KeyDown);

Последнее более применимо, если ScrollViewer находится где-то внутри шаблона и у вас есть код для его поиска.

0 голосов
/ 10 июня 2010

Чтобы ScrollViewer реагировал на ваши клавиши клавиатуры - ему нужно иметь IsFocused = "True" - сейчас его дочерний элемент имеет фокус.

Чтобы доказать это - попробуйте в своем событии Loaded вручную установить фокус на ScrollViewer (вам может потребоваться установить IsFocusable = "True", чтобы он работал на ScrollViewer) - теперь клавиши должны работать. Если вы хотите, чтобы это работало иначе, вам нужно установить соответствующие EventHandlers на ScrollViewer (KeyDown / KeyPress и т. Д.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...