按键事件触发两次

13
在Windows商店应用程序中,我有这个简单的文本框。
<TextBox Name="TextBoxUser" HorizontalAlignment="Right" Width="147" Margin="20,0,0,0" KeyDown="TextBox_KeyDown" /

它与一个KeyDown事件相关联。

        private async void TextBox_KeyDown(object sender, KeyRoutedEventArgs e)
    {
        if (e.Key == Windows.System.VirtualKey.Enter)
        {
           Debug.WriteLine("LA");
        }
    }

这个函数的输出结果是:


LA
LA

尽管我只按了一次回车键,它却打印了两次。有任何原因或者我做错了什么吗?


你确定你没有意外订阅了该事件超过一次吗? - Matthew Watson
4
根据此帖子中的一条回复,显然这是一个错误。我改用了KeyUp事件,现在可以正常工作了。 - Thought
在Windows 10创作者更新版中,UWP TextBox仍然会出现这个问题,但是使用e.Handled = true;可以解决它。 - Martin Suchan
7个回答

17

这应该只触发一次事件,所以如果它触发两次,我会检查一些事情。

检查您是否在父控件上处理按键按下事件。这可以是面板或包含窗口。事件将通过可视树向下传递。例如,在文本框上按下键也将是包含文本框的窗口上的按下键事件。

要停止发生这种情况,您可以将事件标记为已处理,如下所示:

e.Handled = true;
另一个需要检查的事项是,确保您没有订阅事件两次。XAML将执行以下操作;
TextBoxUser.KeyDown += TextBox_KeyDown
因此,请检查您的代码中是否有此内容。
您可以检查sender和e.OriginalSource属性,以查看事件来自何处触发。

1
虽然你的解决方案是正确的,但我认为KeyDown事件存在一个错误! - MAXE
在我的处理程序末尾添加e.Handled = true;就解决了问题。不知道为什么会发生这种情况。我正在监听KeyUp事件,而不是KeyDown事件,但我认为情况是相同的。由于某种原因,事件侦听器会两次获取每个KeyUp事件。这真的是另一个答案中提到的事件中的错误吗? - Alan Thomas
非常好用,非常感谢!在Keyup/down事件的开头添加一个条件来检查e.handled是否为真后就可以使用了! - sanrns

6

这是Windows RT中已知的一个bug。您可以通过检查Key RepeatCount来处理它。

if (e.KeyStatus.RepeatCount == 1)
{
   //Execute code
}

这个 bug 在此期间被修复了吗?当针对 w10 1803 时,我无法再现这个问题。 - Benni

4
我发现KeyDown事件中可能存在一个bug。就像@daniellepelley所说的那样,当我设置了:
e.Handled = true;

事件仍然传播:其他按钮也将拦截它,即使它们不应该。

在我的代码中,我只是用KeyUp事件替换了KeyDown事件,一切都很好(始终将Handled属性设置为True值)!


将 KeyDown 替换为 KeyUp 也解决了我的问题! - Hasan Shouman

1
这可能有点晚了,但是e.preventDefault()对我很有效。特别是在React-TypeScript中。
(e: KeyboardEvent) => {
    e.preventDefault();
    console.log(e);
};

0

我在Xamarin.Android中遇到了同样的问题,即按键事件被触发两次。

在我的情况下,是因为KeyDown和KeyUp是两个单独的操作,它们都调用同一个事件。我只响应其中一个动作,如下所示:

    private void KeyPress(object sender, View.KeyEventArgs e)
    {
        if (e.KeyCode == Keycode.Enter)
        {
            if (e.Event.Action == KeyEventActions.Down)
            {
                Event();
            }
        }
    }

0
void onKeyPressEvent(object sender, KeyEventArgs e)
{
  if(e.Handled)
  return;

  {
    //
    // the block of codes to be executed on the key press
    // should added here.
    //
  }
  e.Handled = true;
}

欢迎来到 Stack Overflow!我们有一份指南 如何撰写优秀的答案。如果您能改进您的回答,那将是非常棒的。谢谢! - David

-1
我在 JavaScript 中遇到了这个问题,即 keydown 事件处理程序被触发两次,通过使用 .off().on() 方法,我成功地解决了这个问题。
$('.text_area').off().on('keydown', function (e) {

// do something

)};

它的作用是关闭额外的事件,获取最新的keydown操作并执行其处理程序

对我来说,只有这个解决方案很好用,谢谢


1
这可以应用于C# / UWP吗? - BDL

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接