Как я могу назначить поведение "Close on Escape-key press" для всех окон WPF в проекте?
Есть ли простой способ сообщить всему приложению WPF реагировать на нажатия клавиши Escape, пытаясь закрыть сфокусированную в настоящее время вдову? Не стоит вручную настраивать привязки команд и ввода, но мне интересно, является ли повторение этого XAML во всех окнах самым элегантным?
<Window.CommandBindings>
<CommandBinding Command="Close" Executed="CommandBinding_Executed" />
</Window.CommandBindings>
<Window.InputBindings>
<KeyBinding Key="Escape" Command="Close" />
</Window.InputBindings>
Любые конструктивные предложения приветствуются!
Ответы
Ответ 1
Все, что я могу предложить, чтобы улучшить это, - это удалить необходимость в обработчике событий путем привязки к экземпляру статической команды.
Примечание: это будет работать только в .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
и что вам не нужно включать обработчик событий в каждый
Ответ 2
Или вы могли бы просто добавить кнопку с Cancel в качестве текста и установить IsCancel = True
. Затем Escape будет работать как команда по умолчанию для закрытия.
Ответ 3
создать 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(); }));
Ответ 4
В Window
с ShowDialog()
вы можете использовать:
<!-- Button to close on Esc -->
<Button IsCancel="True" Width="0" Height="0"/>
Ответ 5
Другим возможным способом является использование прикрепленных свойств
Bellow - это код gist:
<script src="https://gist.github.com/meziantou/1e98d7d7aa6aa859d916.js"></script>
Ответ 6
Вы также можете использовать событие PreviewKeyDown
PreviewKeyDown="UserControl_PreviewKeyDown"
Код за вызовом закрытия команды
private void UserControl_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
_vm.OnCloseCommand(sender);
}
}
Ответ 7
Никто из них не работал у меня, кроме Кай.
Я изменил его ответ: я добавил '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();
}
}
Надеюсь, что это поможет,
Simon
S love nia