2010-10-05 6 views
20

Есть ли простой способ сообщить всему приложению WPF реагировать на нажатия клавиши Escape, пытаясь закрыть сфокусированную вдова? Не очень важно вручную настраивать привязки команд и ввода, но мне интересно, является ли повторение этого XAML во всех окнах самым элегантным?Как назначить поведение «Закрыть по Escape-key press» для всех окон WPF в проекте?

<Window.CommandBindings> 
     <CommandBinding Command="Close" Executed="CommandBinding_Executed" /> 
</Window.CommandBindings> 
<Window.InputBindings> 
     <KeyBinding Key="Escape" Command="Close" /> 
</Window.InputBindings> 

Любые конструктивные предложения приветствуются!

ответ

30

Все, что я могу предложить улучшить, это удалить необходимость в обработчике событий путем привязки к экземпляру статической команды.

Примечание: это будет работать только в .NET 4, поскольку оно требует возможности привязки к свойствам KeyBinding.

Во-первых, создать команду, которая принимает окно в качестве параметра и вызывает Close в Execute метода:

public class CloseThisWindowCommand : ICommand 
{ 
    #region ICommand Members 

    public bool CanExecute(object parameter) 
    { 
     //we can only close Windows 
     return (parameter is Window); 
    } 

    public event EventHandler CanExecuteChanged; 

    public void Execute(object parameter) 
    { 
     if (this.CanExecute(parameter)) 
     { 
      ((Window)parameter).Close(); 
     } 
    } 

    #endregion 

    private CloseThisWindowCommand() 
    { 

    } 

    public static readonly ICommand Instance = new CloseThisWindowCommand(); 
} 

Затем вы можете связать ваш KeyBinding к статическому Instance собственности:

<Window.InputBindings> 
    <KeyBinding Key="Escape" Command="{x:Static local:CloseThisWindowCommand.Instance}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" /> 
</Window.InputBindings> 

Я не знаю, что это обязательно лучше, чем ваш подход, но это означает минимально меньшее количество шаблонов в верхней части каждого Window и что вам не нужно включать обработчик событий в каждом

+0

может ли это привести к утечки памяти, так как у singleton есть «EventHandler»? – Maslow

+0

Этого не должно быть, но поскольку мы действительно не заботимся о функциях «CanExecute», которые вы можете защитить от него, если «CanExecute» всегда возвращает true и заменяет обработчик «CanExecuteChanged» пустыми реализациями вложений (например, «public event EventHandler» CanExecuteChanged {add {} remove {}} ') –

20

Или вы можете просто добавить кнопку с Отменением в виде текста и установить IsCancel = True. Затем Escape будет работать как команда по умолчанию для закрытия.

+1

не всегда идеален, но все равно нравится предложение. Достаточно просто. –

2

создать RoutedUICommand как ниже

private static RoutedUICommand EscUICommand = new RoutedUICommand("EscBtnCommand" 
     , "EscBtnCommand" 
     , typeof(WindowName) 
     , new InputGestureCollection(new InputGesture[] 
      { new KeyGesture(Key.Escape, ModifierKeys.None, "Close") })); 

и добавить его в командном связывании конструктору

CommandBindings.Add(new CommandBinding(EscUICommand, (sender, e) => { this.Hide(); })); 
-1

Ни одно из вышеперечисленного не работал для меня, кроме Кая. Я изменил его ответ: я добавил 'btn_close.IsCancel = true;' к конструктору. SettingsWindow - это мое второе окно, а главное окно (по умолчанию) MainWindow.

public partial class SettingsWindow : Window { 
    public SettingsWindow() { 
     InitializeComponent(); 
     btn_close.IsCancel = true; 
    } 
    private void btn_close_Click(object sender, RoutedEventArgs e) { 
     this.Close(); 
    } 
    } 

Надеется, что это помогает,

Саймона S любовь NIA

0

Других возможным способ заключается в использовании присоединенных свойств

Бельего код сути:

<script src="https://gist.github.com/meziantou/1e98d7d7aa6aa859d916.js"></script>

1

На Window ы показано ShowDialog() вы можете использовать:

<!-- Button to close on Esc --> 
<Button IsCancel="True" Width="0" Height="0"/> 
0

Вы можете также использовать PreviewKeyDown Event

PreviewKeyDown="UserControl_PreviewKeyDown" 

код за позвоню команда закрытия

private void UserControl_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e) 
     { 
      if (e.Key == Key.Escape) 
      { 
       _vm.OnCloseCommand(sender); 
      } 
     }