C# 如何使用escape键在WPF中关闭窗口

C# 如何使用escape键在WPF中关闭窗口,c#,.net,wpf,xaml,C#,.net,Wpf,Xaml,可能重复: 我想在用户单击escape按钮时关闭wpf项目中的窗口。我不想在每个窗口中都编写代码,而是想创建一个类,当用户按escape键时,该类可以捕获错误。选项1 使用属性 <Button Name="btnCancel" IsCancel="true" Click="OnClickCancel">Cancel</Button> 在InitializeComponent()之后放置一行: 请注意,这种代码隐藏不会破坏MVVM模式,因为它与UI相关,并且您不访问任何

可能重复:


我想在用户单击escape按钮时关闭wpf项目中的窗口。我不想在每个窗口中都编写代码,而是想创建一个类,当用户按escape键时,该类可以捕获错误。

选项1

使用属性

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

在InitializeComponent()之后放置一行:


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

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

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

<Window.CommandBindings>
  <CommandBinding Command="ApplicationCommands.Close" Executed="CloseCommandBinding_Executed" />
</Window.CommandBindings>
您可以创建一个自定义:

使用System.Windows;
使用System.Windows.Input;
公共静态类窗口实用程序
{
/// 
///属性以允许按Esc键关闭窗口。
/// 
公共静态只读DependencyProperty CloseOnEscapeProperty=DependencyProperty.RegisterAttached(
“CloseOnEscape”,
类型(bool),
类型(窗口实用程序),
新的FrameworkPropertyMetadata(false,CloseOnEscapeChanged));
公共静态bool GetCloseOnEscape(DependencyObject d)
{
返回(bool)d.GetValue(CloseOnEscapeProperty);
}
公共静态void SetCloseOnEscape(DependencyObject d,布尔值)
{
d、 SetValue(CloseOnEscapeProperty,value);
}
私有静态void CloseOnEscapeChanged(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
如果(d是窗口目标)
{
if((bool)e.NewValue)
{
target.PreviewKeyDown+=窗口_PreviewKeyDown;
}
其他的
{
target.PreviewKeyDown-=窗口_PreviewKeyDown;
}
}
}
私有静态无效窗口_PreviewKeyDown(对象发送方,KeyEventArgs e)
{
如果(发送方是窗口目标)
{
if(e.Key==Key.Escape)
{
target.Close();
}
}
}
}
并将其用于windows的XAML,如下所示:

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


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

此处的
InputBinding
选项既漂亮又灵活

如果要使用事件处理程序,请注意
预览
事件发生得很早。如果您有一个嵌套控件,该控件出于自身目的应使用Esc键,则在窗口级别窃取它可能会阻止该控件的功能

相反,只有在没有其他事情需要处理时,才能在窗口级别处理事件:

受保护的覆盖无效OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
如果(!e.Handled&&e.Key==Key.Escape&&Keyboard.Modifiers==ModifierKeys.None)
{
这个。关闭();
}
}

这不是我的解决方案。。我甚至不想在每个窗口都做这件事。我想用一种风格来写,但那不起作用,因为风格中没有属性。请查看[这][1]帖子-它准确地解释了如何实现这一点[1]:这是一个可能的重复,我不想使用按钮…任何硬件谢谢,我找到了solution@kishorejangid:第二个代码示例没有使用按钮。@kishorejangid-你能在这里发布你的答案吗?Enter有类似的功能吗?你可以在按钮上设置IsDefault=“True”,让Enter执行与单击按钮相同的操作。
<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();
}
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();
            }
        }
    }
}
<Window ...
    xmlns:custom="clr-namespace:WhereverThePropertyIsDefined"
    custom:WindowUtilities.CloseOnEscape="True"
    ...>