我有一个带有自定义数据模板的ListBox,其中包含CheckBox,TextBlock和TextBox。通常,当您在ListBox中选择一个项目时,基础ListBoxItem实际上是具有焦点的项目,因此它响应向上和向下键。另外,如果CheckBox具有焦点,因为它对上下键本身没有任何作用,它只是很乐意忽略它们,它们也由底层ListBoxItem处理。到目前为止一切都很好。
然而,TextBox有自己的上下键处理规则,命名地在文本中向上或向下移动插入符号,这在这里不适用,因为在这种情况下它是一行(它实际上是一个数字) 。)因此,如果TextBox具有焦点,则向上和向下键会破坏ListBox选择的导航,也不会真正帮助编辑。
现在虽然我可以处理PreviewKeyDownEvent(我在下面做,但出于不同的原因)并根据按下的键手动处理行为,这是一个非常具体的解决方案,需要控件知道其容器的行为。< / p>
在一个完美的世界(和伪代码)中,我只想说MyTextBox.KeysToIgnore(向上,向下)或类似的东西,让它做到这一点......忽略那些键,好像它不是那里。 (再次,不要吞下,但要忽略,以便他们通过。)
但是在那之前,这就是我想出来的,这似乎有用,但看起来对我来说太'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,这是有道理的,但随后我用PreviewKeyUp和KeyUp事件打了另一面墙,这要归功于设置e在上面,我从来没有得到真正的“关键”事件来知道什么时候发送假的。另外,我很确定我也会打破PreviewKeyxxx消息的方向,因为它们与常规的非预览版本相反。 (也许这是在内部处理的,但我不这么认为。)
就像我说的那样...... hacky,hacky,hacky!
但它确实有效,所以就是这样。我可以通过附加行为实现这一点,这就是为什么我甚至走这条路。 (在附加的行为实现中,它不是case语句,而是对我在XAML中指定的键集合的检查。)我只是不喜欢失去我想要的所有其他行为的想法。
同样,我只想说'嘿TextBox ......当你看到按下向上或向下键时,STFU呀b * stard !!'并使密钥透明。
有人想到吗?
答案 0 :(得分:1)
男人......甚至没有一条评论,更不用说近一个月的答案了!哦,好吧......猜猜我上面的'hacky'解决方案是这样做的,所以我把它标记为答案。
答案 1 :(得分:1)
是的,TextBox关键事件处理肯定会让你头疼。 问题是无法确定通过EventManager.RegisterClassEventHandler注册的回调的调用顺序。即你的回调在未处理的事件上调用,然后处理事件,就是这样...... 我找到了一种通过继承TextBox并在构造函数中调用“AddEventHandler(KeyDownEvent,callback,true)”来“解锁”键事件的方法。然后根据情况设置e.Handled = false。看起来像在TextBox处理事件后调用回调。 每个TextBox实例都有委托实例非常不好,而不是每个类都有一个委托实例,但我看不到任何其他解决方法。