【问题标题】:How to ignore Enter key from WPF modal dialog, in PreviewKeyUp如何在 PreviewKeyUp 中忽略 WPF 模式对话框中的 Enter 键
【发布时间】:2013-06-29 02:16:27
【问题描述】:

我有一个 WPF 应用程序。在它的主窗口上,它有一个 PreviewKeyUp 处理程序,用于处理某些全局按键 - 在本例中为 Enter。 我发现当显示模式对话框(ShowDialog)并按下回车键时,回车进入主窗口上的 PreviewKeyUp 处理程序。 根据您的观点,这可能有意义,也可能没有意义……但这绝对不是我想要的。

所以我看不到任何方法可以在主窗口上可靠地拦截 Enter 键(无论集中控制如何),而在模式对话框中按下 Enter 键时也不会被调用。

这似乎是特定于 Enter 键的行为 - 它不会发生在其他键上,例如数字。

有人有什么想法吗?

主窗口代码:

private void Window_PreviewKeyUp(object sender, KeyEventArgs e)
{
  switch (e.Key)
  {
    case Key.Enter:
      Controller.ProductSelected();
      ActionComplete();
      e.Handled = true;
      break;
  }
}


public bool PromptForPassword(string promptText, out string result)
{
  DataEntryForm entryForm = new DataEntryForm();
  entryForm.Owner = this;
  entryForm.PromptText = promptText;

  IsEnabled = false; // doesn't help
  entryForm.ShowDialog();
  IsEnabled = true;

  result = entryForm.EntryData;

  return (bool) entryForm.DialogResult;
}

【问题讨论】:

  • 在显示对话框之前,您是否尝试过在主窗口中设置 IsEnabled = false?
  • 刚刚尝试过 - 不会停止 PreviewKeyUp 触发。在 PreviewKeyUp 触发时,该窗口似乎已重新启用。也会有点难看,因为我必须记住在每个 ShowDialog 周围都这样做。
  • 现在刚试的时候,有没有用Dispatcher.BeginInvoke?我检查了我的,PKU 事件被吞了。
  • 我没有使用任何 Invoke 或 BeginInvoke(或一般的后台线程)...
  • 如果它对你有用的话,我就这么做了... Dispatcher.BeginInvoke(DispatcherPriority.Input, (SendOrPostCallback)delegate { IsEnabled = false; }, new object[] { null }); var dr = MessageBox.Show("你好"); Dispatcher.BeginInvoke(DispatcherPriority.Input, (SendOrPostCallback)delegate { IsEnabled = true; }, new object[] { null });并且 ENTER 键消失了

标签: .net wpf dialog keyboard modal-dialog


【解决方案1】:

在那种情况下,如果对你有用的话,我会这样做......

Dispatcher.BeginInvoke(DispatcherPriority.Input, 
            (SendOrPostCallback)delegate { IsEnabled = false; }, new object[] { null }); 
var dr = MessageBox.Show("Hello"); 
Dispatcher.BeginInvoke(DispatcherPriority.Input, 
            (SendOrPostCallback)delegate { IsEnabled = true; }, new object[] { null }); 

ENTER 会被对话框吞掉。

【讨论】:

  • 谢谢加里。如前所述,我不明白为什么需要 Dispatcher.BeginInvoke,但这确实有效,而且没有 BeginInvoke 就无法工作。
  • 我后来发现这个解决方案不太实用。我需要将焦点重新回到表单上,这会导致再次处理 Enter 键。查看我的其他解决方案...
【解决方案2】:

我发现 Garry 的解决方案留下了焦点问题。

这个问题似乎只有在对话框中的“确定”按钮上使用 IsDefault 时才会出现。因此,一个没有副作用的简单解决方案是在 PreviewKeyUp 事件中处理回车键。

public partial class MyDialog : Window
{
    ...

    private void Window_PreviewKeyUp(object sender, KeyEventArgs e)
    {
        switch(e.Key)                
        {
            case Key.Enter:
                OKButton_Click(sender,e);
                break;
        }

    }

这可能是访问键的普遍问题,因为按回车键按应该是通过注册访问键来处理的。也许是这个访问密钥范围问题: http://coderelief.net/2012/07/29/wpf-access-keys-scoping/

缺点是您必须更改所有对话框窗口才能以这种方式工作 - 有点难看,但代码不多。

【讨论】:

    【解决方案3】:

    这个问题更简单和包容的解决方案是捕捉按键事件,而不是让它继续到顶部对话框后面的对话框:

    private void Window_PreviewKeyUp(object sender, KeyEventArgs e)
    {
            // whatever your code should do when the event fires...
    
            // swallow Enter key so it won't
            // press buttons under the current dialog
            e.Handled = true;
     }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-22
      • 1970-01-01
      • 2016-02-25
      • 2020-08-29
      • 2017-06-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多