如何在转义键上关闭WPF中的窗口

时间:2011-10-07 19:01:21

标签: c# .net wpf c#-4.0

  

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

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

5 个答案:

答案 0 :(得分:114)

选项1

使用Button.IsCancel属性。

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

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

但是,这仅适用于Dialogs。

选项2

如果要在Esc按下关闭窗口,可以在窗口上为PreviewKeyDown添加处理程序。

public MainWindow()
{
    InitializeComponent();

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

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

答案 1 :(得分:4)

这是一种无按钮的解决方案,它干净且具有更多的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();
}

答案 2 :(得分:2)

在InitializeComponent()之后放置一行:

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

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

答案 3 :(得分:0)

您可以创建自定义DependencyProperty

int[] data = new int[] { 65, 66, 67, 32, 100, 90 };
List<int> list = new List<int>();
list.AddRange(data);

像这样在Windows的XAML中使用它:

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();
            }
        }
    }
}

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

答案 4 :(得分:0)

此处的 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();
    }
}