2010-10-05 9 views
20

¿Hay alguna forma directa de decirle a toda la aplicación WPF que reaccione ante las pulsaciones de tecla Escape intentando cerrar la ventana actualmente enfocada? No es una gran molestia configurar manualmente el comando y los enlaces de entrada, pero me pregunto si la repetición de este XAML en todas las ventanas es el enfoque más elegante.¿Cómo puedo asignar el comportamiento 'Cerrar en la tecla de escape' a todas las ventanas de WPF dentro de un proyecto?

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

Todas las sugerencias constructivas son bienvenidas!

Respuesta

30

Todo lo que puedo sugerir para mejorar es eliminar la necesidad de un controlador de eventos mediante el enlace a una instancia de comando estático.

Nota: esto solo funcionará en .NET 4 en adelante, ya que requiere la capacidad de vincularse a las propiedades KeyBinding.

En primer lugar, crear un comando que tiene una ventana como un parámetro y llama Close dentro del Execute método:

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

Entonces se puede vincular a su KeyBinding a la Instance propiedad estática:

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

No sé si esto es necesariamente mejor que su enfoque, pero significa marginalmente menos repetitivo en la parte superior de cada Window y que no necesita incluir un controlador de eventos en cada

+0

podrían suponer un pérdidas de memoria ya que el singleton tiene un 'EventHandler'? – Maslow

+0

No debería ser así, pero como realmente no nos importa la funcionalidad 'CanExecute', podemos protegerla haciendo que' CanExecute' siempre devuelva verdadero y reemplace el controlador 'CanExecuteChanged' con implementaciones de adjuntos vacíos (p. Ej.' Public event EventHandler CanExecuteChanged {add {} remove {}} ') –

20

O simplemente podría agregar un botón con Cancelar como texto y establecer IsCancel = True. Entonces, Escape funcionará como comando predeterminado para cerrar.

+1

no siempre es ideal, pero sigue siendo como la sugerencia. Suficientemente simple. –

2

crear RoutedUICommand, como a continuación

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

y agregarlo comando de unión en el constructor

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

Ninguna de las anteriores trabajó para mí, si Kai. Modifiqué su respuesta: agregué 'btn_close.IsCancel = true;' al constructor SettingsWindow es mi segunda ventana, y la ventana principal es (por defecto) MainWindow.

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

creo que sirve,

Simon S nia amor

0

Otra forma posible es utilizar las propiedades asociadas

Bellow es un código de GIST:

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

1

En Window S mostrado con ShowDialog() puede utilizar:

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

También puede utilizar PreviewKeyDown Evento Código

PreviewKeyDown="UserControl_PreviewKeyDown" 

detrás de usted llame orden de cierre

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