【问题标题】:Keyboard.IsKeyDown always returns trueKeyboard.IsKeyDown 总是返回 true
【发布时间】:2016-06-16 22:00:19
【问题描述】:

我有一个带有输入绑定的 UI。

<Window.InputBindings>
<KeyBinding 
    Key="Up" 
    Command="{Binding Up}" />

我想使用这个键绑定来向下滚动各种元素。我可以通过这样的方法在 Windows 中使用 in build key-down repeat。

    public void selectionUp()
    {
        SelectionNo += 1;
    }

这行得通。如果我按向上键,选择将向上移动。但是,我不喜欢基于用户在 Windows 中重复键盘的任何设置,事件一开始似乎触发得很慢的方式。所以我想做这样的事情:

  • KeyPressedEvent 命中
  • KeyDown bool 设置为 true
  • 当 KeyDown 为真时
    • +1 选择
    • 更新用户界面
    • Check Key 仍处于关闭状态
    • 如果没有,则更新 KeyDown bool

所以我最终得到了这样的方法......

        public void positionUp()
    {
        if (!keyUpIsDown) //needed to prevent this while loop being accessed multiple times
        {
            keyUpIsDown = true;
            while (keyUpIsDown)
                {
                SelectionNo += 1;
                if (Keyboard.IsKeyUp(Key.Up))
                {
                    keyUpIsDown = false;
                }
            }
        }
    }

我遇到的问题是'if (Keyboard.IsKeyUp(Key.Up))' 总是说即使我释放了键,键也已关闭。

我该如何解决这个问题?

【问题讨论】:

  • 您可能无法让消息循环运行,因此永远不会处理 keyup 消息 - 此代码是否在 UI 线程上?
  • @davidbak 这也是我的想法。但是 WPF 没有 Application.DoEvents 所以我的默认答案不起作用。
  • 在 SelectionNo 更改时更新 UI 很难从后台线程正确执行。如果我的异步想法不起作用,我会尝试在 UI 线程上运行的 Timer(例如 DispatcherTimer)。
  • @hvd 虽然您的观点在一般情况下是有效的,但他编写的应用程序类型可能会改变规则。我记得一些较旧的游戏使用操作系统设置进行延迟/重复,这使得控件相当生涩。
  • Lewis Heslop 为什么这样做实际上并不重要。只要它修复了键盘状态,其他任何遇到此问题的人都不会在意。 (而且他们可能正在查看您无法争辩的东西,例如 Shift 键状态。)

标签: c# wpf user-interface keyboard-events


【解决方案1】:

您需要让它有机会处理来自操作系统的事件。一种方法是使您的代码异步并添加 Task.Delay。

  public async void positionUp()
{
    if (!keyUpIsDown) //needed to prevent this while loop being accessed multiple times
    {
        keyUpIsDown = true;
        while (keyUpIsDown)
            {
            SelectionNo += 1;
            if (Keyboard.IsKeyUp(Key.Up))
            {
                keyUpIsDown = false;
            }
            await Task.Delay(100); //you will need to tune this, but it can't be 0
        }
    }
}

【讨论】:

  • 我会试试这个并反馈。
  • 好东西.. 完美无瑕,似乎我什至可以将延迟设置为 1 毫秒,一切都很好。
  • 在我接受它作为答案之前,我会让其他用户有机会发表他们的想法!
  • Jonathan,在这种情况下,await Task.Yield() 和 away Task.Delay(0) 似乎不起作用,keyUpIsDown 永远不会设置为 false。
  • 好的,我改了答案。
猜你喜欢
  • 2013-08-06
  • 2017-05-10
  • 2013-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多