我有一个带有自定义数据模板的 ListBox,其中包含一个 CheckBox、一个 TextBlock 和一个 TextBox。通常,当您在 ListBox 中选择一个项目时,底层的 ListBoxItem 实际上是具有焦点的,因此它会响应向上和向下键。此外,如果 CheckBox 有焦点,因为它本身不使用 up 和 down 键做任何事情,它只是很高兴地忽略它们并且它们也由底层 ListBoxItem 处理。到目前为止一切都很好。
但是,TextBox 对向上和向下键有自己的处理规则,即在文本中将插入符号向上或向下移动一行,这在此处不适用,因为在这种情况下它是单行(实际上是一个数字)。这样,如果 TextBox 具有焦点,则向上和向下键会破坏 ListBox 选择的导航,它们也不会真正帮助编辑。
现在,虽然我可以处理 PreviewKeyDownEvent(我在下面这样做,但出于不同的原因)并根据按下的键手动处理行为,但这是一个非常具体的解决方案,并且需要控件了解其容器的行为。
在一个完美的世界(和伪代码)中,我只想说 MyTextBox.KeysToIgnore(Up, Down) 或类似的东西,让它这样做......忽略那些键,就好像它根本不存在一样。(再一次,不要吞下,而是忽略,让他们通过。)
但在那之前,这就是我想出的,这似乎有效,但对我来说看起来很“hacky”......
private void PreviewKeyDownHandler(object sender, KeyEventArgs e) {
switch (e.Key){
case Key.Up:
case Key.Down:
case Key.OtherKeyToIgnore
case Key.AndAnother
e.Handled = true;
FrameworkElement target = VisualTreeHelper.GetParent(
e.Source as DependencyObject) as FrameworkElement;
target.RaiseEvent(
new KeyEventArgs(
e.KeyboardDevice,
PresentationSource.FromVisual(target),
0,
e.Key
){
RoutedEvent=Keyboard.KeyDownEvent
}
);
break;
}
}
这也增加了不向目标发送 PreviewKeyDown 事件的负面影响。现在我可以解决这个问题并通过首先发送该事件来伪造它,然后在发送实际的 KeyDown 消息之前查看 e.Handled,这是有道理的,但是由于设置 e,我用 PreviewKeyUp 和 KeyUp 事件撞到了另一面墙.在上面处理,我从来没有得到真正的'key up'事件来知道什么时候发送假的。另外,我很确定我也会破坏 PreviewKeyxxx 消息的方向,因为它们与常规非预览版本的方向相反。(也许这是内部处理的,但我不这么认为。)
就像我说的...... hacky,hacky,hacky!
但它确实有效,所以就是这样。我可以通过附加行为来实现这一点,这就是我什至走这条路的原因。(在附加的行为实现中,它不是 case 语句,而是对我在 XAML 中指定的键集合进行检查。)我只是不喜欢丢失所有其他我想要的行为的想法。
再说一次,我只想说“嘿,TextBox……当你看到向上或向下键被按下时,STFU ya b*stard!!” 否则使其密钥透明。
有人想吗?