【问题标题】:WPF: OnKeyDown() not being called for space key in control derived from WPF TextBoxWPF:从 WPF 文本框派生的控件中没有为空格键调用 OnKeyDown()
【发布时间】:2009-09-22 08:17:50
【问题描述】:

在 WPF 应用程序中,我有一个从 TextBox 派生的控件,如下所示:

public class SelectableTextBlock : TextBox
{
    protected override void OnKeyDown(KeyEventArgs e)
    {
        base.OnKeyDown(e);
        e.Handled = false;
    }
}

在 TextBox 中输入空格或按 Backspace 时不会调用 OnKeyDown 方法,但会触发其他输入,包括正常的可打印字符(例如 'a')和修饰键(例如 )。

我正在使用这个控件,并将 IsReadOnly 设置为 true,这样我就可以显示可选择的、不可编辑的文本。 WPFToolkit 的 DataGrid 中使用的控件,我希望 KeyDown 事件能够向上传播数据网格,即使 SelectableTextBlock 具有焦点,这就是我使用自定义控件将事件显式标记为未处理的原因。

问题是事件甚至没有让我控制某些键。我不能只在 DataGrid 中使用 OnPreviewKeyDown 来解决这个问题,因为我确实希望数据网格中使用的其他控件能够吞下空间 KeyDown 事件。

有谁知道我怎样才能让空格键向上传播的 KeyDown 事件?

谢谢。

【问题讨论】:

    标签: c# wpf textbox onkeydown


    【解决方案1】:

    PreviewKeyDown 事件正是针对这类事情而存在的。

    private void spacebarHandler_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Space)
            e.Handled = true;
    }
    

    您的 KeyDown 处理程序将永远不会收到空格键的 KeyDown 事件。

    【讨论】:

    • 为什么要写一个新的处理程序。为什么不只是这个:protected override void OnPreviewKeyDown(KeyEventArgs e) { if (e.Key == Key.Space) e.Handled = true; }
    【解决方案2】:

    似乎问题在于空格(和退格等)按键事件已经在 TextBox 中处理,然后它会冒泡到我的派生控件。正如 Wim 所发布的,我认为这是文本撰写过程的一部分。

    为了解决这个问题,我添加了一个处理程序,即使它已经被处理,它也会接收按键按下事件,并将其 Handled 成员设置为 false,以允许它继续正常冒泡。在下面的示例中,它仅针对空格键执行此操作,但在我的情况下,我需要对我 真正 不想在我的 SelectedableTextBlock 中处理的任何键事件执行此操作,因为我还不知道父母可能对哪些关键事件感兴趣。

    public class SelectableTextBlock : TextBox
    {
        public SelectableTextBlock() : base()
        {
            this.AddHandler(SelectableTextBlock.KeyDownEvent, new RoutedEventHandler(HandleHandledKeyDown), true);
        }
    
        public void HandleHandledKeyDown(object sender, RoutedEventArgs e)
        {
            KeyEventArgs ke = e as KeyEventArgs;
            if (ke.Key == Key.Space)
            {
                ke.Handled = false;
            }
        }
        ...
    }
    

    如果有人有更好的解决方案,我当然仍然感兴趣......

    谢谢, E.

    【讨论】:

      【解决方案3】:

      派生出一个说法,RestrictKeysTextBox from TextBox。

      public class RestrictKeysTextBox : TextBox
      {
          ....
      }
      

      覆盖 RestrictKeysTextBox 中的 OnPreviewKeyDown 事件。

      将逻辑放入此覆盖中,如下所示:

      if (e.Key == Key.Space)
      {
          e.Handled = true;
      }
      

      将 RestrictKeysTextBox 的实例绑定到您的 DataGrid。

      这应该可以在不覆盖 DataGrid 中的 OnPreviewKeyDown 的情况下工作并消除相关问题。

      【讨论】:

        【解决方案4】:

        我曾经在文本框中遇到过空格和事件的问题。是否仅在添加或删除空格字符时才触发事件?

        这是我得到的答案:(http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/446ec083-04c8-43f2-89dc-1e2521a31f6b)

        因为某些 IME 会将空格键击视为文本合成过程的一部分,这就是为什么 Avalon 会通过 TextInput 事件报告正确的合成文本。

        我可能完全不在讨论范围内,但是阅读这个帖子让我想起了我曾经遇到的那个问题。

        亲切的问候, 维姆

        【讨论】:

        • 感谢您的回复,维姆。这似乎是一个相关的问题。我发现空格字符和退格键和删除键不会触发该事件。而在您的情况下,您试图阻止文本框处理空格键并通过处理预览来完成,我试图让事件冒泡到父控件,所以这对我不起作用。我有一个解决方法来处理已处理的按键事件并将它们设置为已处理。我将发布代码以引起普遍兴趣,以回复我的原始问题。仍然认为必须有更好的方法。谢谢,E。
        • 应该是这样的:“我有一个解决方法来处理已处理的按键事件并将它们设置为未处理。”
        猜你喜欢
        • 1970-01-01
        • 2015-10-07
        • 2010-12-17
        • 2016-06-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-24
        相关资源
        最近更新 更多