2

我有一个带有自定义数据模板的 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!!” 否则使其密钥透明。

有人想吗?

4

2 回答 2

1

伙计……甚至没有一条评论,更不用说将近一个月的答复了!哦,好吧...猜我上面的“hacky”解决方案就是这样做的方法,所以我将其标记为答案。

于 2010-11-10T06:01:48.110 回答
1

是的,TextBox 键事件处理肯定会让你头疼。问题是无法确定回调的调用顺序,通过 EventManager.RegisterClassEventHandler 注册。即你的回调在未处理的事件上被调用,然后事件被处理,就是这样......我找到了一种通过子类化TextBox并在构造函数中调用“AddEventHandler(KeyDownEvent,callback,true)”来“处理”关键事件的方法。然后根据情况设置 e.Handled = false 。似乎在 TextBox 处理事件后调用回调。每个 TextBox 实例都有一个委托实例,而不是每个类有一个委托实例,这是非常不好的,但我看不到任何其他解决方法。

于 2010-11-30T12:49:58.977 回答