C# 为什么';当子控件具有输入焦点时,ScrollViewer的键盘输入是否工作?

C# 为什么';当子控件具有输入焦点时,ScrollViewer的键盘输入是否工作?,c#,wpf,xaml,C#,Wpf,Xaml,为什么当子控件具有输入焦点时,ScrollViewer的键盘输入不起作用 情况就是这样。将打开一个WPF窗口。它将焦点设置为嵌入ScrollViewer中的控件 我按上下左右键。ScrollViewer似乎无法处理关键事件,有人知道为什么吗 这是最简单的例子: <Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

为什么当子控件具有输入焦点时,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对此进行了检查)。我不明白它为什么不响应输入。

为了让ScrollViewer对键盘键做出反应-它需要有IsFocused=“True”-现在它的孩子有焦点


为了证明这一点,请尝试在加载的事件中手动设置ScrollViewer的焦点(您可能必须设置IsFocusable=“True”才能使其在ScrollViewer上工作)-现在按键应该可以工作了。如果您希望它以其他方式工作,则需要在ScrollViewer上设置适当的事件处理程序(KeyDown/KeyPress等)

解决问题

ScrollViewer忽略其原始源不是ScrollViewer的所有按键向下事件。向下键上的OriginalSource设置为焦点控件,因此当子控件具有焦点时,ScrollViewer将忽略它

解决方案

捕获KeyDown事件并直接在ScrollViewer上生成它的副本,这样它将具有正确的原始源,如下所示:

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位于某个模板中,并且您有代码可以找到它,则后者更适用。

ItemsControl.template
中使用
ScrollViewer
时没有键盘导航的类似问题。添加
Focusable
IsTabStop
解决了我的问题

<ScrollViewer
    Focusable="True"
    IsTabStop="True">
    <ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
 </ScrollViewer>


谢谢,但我想你误解了这个问题。我想让孩子集中注意力。在我的应用程序中,该子程序处理输入,然后事件跳转到ScrollViewer。问题是为什么ScrollViewer不能处理它们?如果ScrollViewer没有焦点,则箭头键的“自动映射”无法工作。正如我在回答中所写的那样,您需要将处理程序附加到Keyevents。在您的代码中,您不处理事件。谢谢,这听起来很有用,我将尝试一下。虽然我很想知道设计的原因,如果有,为什么它不能像我期望的那样工作。我不知道,但我知道他们做了很多可用性测试。我的猜测是,他们发现使用ScrollViewer时,可用性受到了影响,而ScrollViewer没有焦点。换言之,我怀疑用户会发现当按钮聚焦时箭头导致滚动时出现意外和/或意外的行为。
<ScrollViewer
    Focusable="True"
    IsTabStop="True">
    <ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
 </ScrollViewer>