【问题标题】:How to Close a Window in WPF on a escape key如何在 WPF 中使用转义键关闭窗口
【发布时间】:2011-12-03 06:02:24
【问题描述】:

可能重复:
How can I assign the 'Close on Escape-key press' behavior to all WPF windows within a project?

当用户单击退出按钮时,我想关闭我的 wpf 项目中的窗口。我不想在每个窗口中都编写代码,但想创建一个可以在用户按下转义键时捕获的类。

【问题讨论】:

标签: c# .net wpf xaml


【解决方案1】:

选项 1

使用Button.IsCancel 属性。

<Button Name="btnCancel" IsCancel="true" Click="OnClickCancel">Cancel</Button>

当您将按钮的 IsCancel 属性设置为 true 时,您将创建一个 使用 AccessKeyManager 注册的按钮。按钮是 然后在用户按下 ESC 键时激活。

但是,这仅适用于对话框。

选项2

如果您想在 Esc 按下时关闭窗口,您可以在窗口上的 PreviewKeyDown 添加一个处理程序。

public MainWindow()
{
    InitializeComponent();

    this.PreviewKeyDown += new KeyEventHandler(HandleEsc);
}

private void HandleEsc(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Escape)
        Close();
}

【讨论】:

  • 我不想使用按钮...谢谢,我找到了解决方案
  • @kishorejangid:第二个代码示例没有使用按钮。
  • @kishorejangid - 你能在这里发表你的答案吗?
  • Enter 有类似的吗?
  • 您可以在按钮上设置 IsDefault="True" 以使输入与单击按钮相同。
【解决方案2】:

这是一个无按钮的解决方案,它干净且更 MVVM 风格。将以下 XAML 添加到您的对话框/窗口中:

<Window.InputBindings>
  <KeyBinding Command="ApplicationCommands.Close" Key="Esc" />
</Window.InputBindings>

<Window.CommandBindings>
  <CommandBinding Command="ApplicationCommands.Close" Executed="CloseCommandBinding_Executed" />
</Window.CommandBindings>

并在代码隐藏中处理事件:

private void CloseCommandBinding_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
{
  if (MessageBox.Show("Close?", "Close", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
    this.Close();
}

【讨论】:

    【解决方案3】:

    在 InitializeComponent() 之后放置一行:

     PreviewKeyDown += (s,e) => { if (e.Key == Key.Escape) Close() ;};
    

    请注意,这种背后的代码不会破坏 MVVM 模式,因为这是与 UI 相关的,并且您不会访问任何视图模型数据。另一种方法是使用需要更多代码的附加属性。

    【讨论】:

      【解决方案4】:

      您可以创建自定义DependencyProperty

      using System.Windows;
      using System.Windows.Input;
      
      public static class WindowUtilities
      {
          /// <summary>
          /// Property to allow closing window on Esc key.
          /// </summary>
          public static readonly DependencyProperty CloseOnEscapeProperty = DependencyProperty.RegisterAttached(
             "CloseOnEscape",
             typeof(bool),
             typeof(WindowUtilities),
             new FrameworkPropertyMetadata(false, CloseOnEscapeChanged));
      
          public static bool GetCloseOnEscape(DependencyObject d)
          {
              return (bool)d.GetValue(CloseOnEscapeProperty);
          }
      
          public static void SetCloseOnEscape(DependencyObject d, bool value)
          {
              d.SetValue(CloseOnEscapeProperty, value);
          }
      
          private static void CloseOnEscapeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
          {
              if (d is Window target)
              {
                  if ((bool)e.NewValue)
                  {
                      target.PreviewKeyDown += Window_PreviewKeyDown;
                  }
                  else
                  {
                      target.PreviewKeyDown -= Window_PreviewKeyDown;
                  }
              }
          }
      
          private static void Window_PreviewKeyDown(object sender, KeyEventArgs e)
          {
              if (sender is Window target)
              {
                  if (e.Key == Key.Escape)
                  {
                      target.Close();
                  }
              }
          }
      }
      

      然后像这样使用你的 Windows 的 XAML:

      <Window ...
          xmlns:custom="clr-namespace:WhereverThePropertyIsDefined"
          custom:WindowUtilities.CloseOnEscape="True"
          ...>
      

      答案基于this answer中引用的要点内容。

      【讨论】:

        【解决方案5】:

        这里的InputBinding 选项既好用又灵活。

        如果您想使用事件处理程序,请注意Preview 事件很早就发生了。如果您有一个嵌套控件应该为自己的目的使用 Esc 键,那么在窗口级别窃取它可能会破坏该控件的功能。

        相反,只有在没有其他需要的情况下,您才可以在窗口级别处理事件:

        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);
        
            if (!e.Handled && e.Key == Key.Escape && Keyboard.Modifiers == ModifierKeys.None)
            {
                this.Close();
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2015-04-12
          • 1970-01-01
          • 2019-07-21
          • 2019-12-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-26
          相关资源
          最近更新 更多