2010-10-05 8 views
20

C'è un modo semplice per dire all'intera applicazione WPF di reagire alle pressioni dei tasti di escape tentando di chiudere la vedova attualmente focalizzata? Non è un gran fastidio impostare manualmente i collegamenti di comando e di input, ma mi chiedo se ripetere questo XAML in tutte le finestre sia l'approccio più elegante?Come posso assegnare il comportamento "Chiudi su Escape-key press" a tutte le finestre WPF all'interno di un progetto?

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

Qualsiasi suggerimento costruttivo benvenuto!

risposta

30

Tutto quello che posso suggerire di migliorare è quello di rimuovere la necessità di un gestore di eventi legandosi a un'istanza di comando statico.

Nota: questo funzionerà solo in .NET 4 in poi poiché richiede la capacità di collegarsi alle proprietà KeyBinding.

In primo luogo, creare un comando che prende una finestra come parametro e chiama Close all'interno del metodo 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(); 
} 

Quindi è possibile vincolare il proprio KeyBinding alla statica Instance proprietà:

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

Non so che questo sia necessariamente meglio rispetto al tuo approccio, ma significa leggermente più basso numero di piastre nella parte superiore di ogni Window e che non è necessario includere un gestore eventi in ogni

+0

può questo portare a perdite di memoria dal momento che il singleton ha un 'EventHandler'? – Maslow

+0

Non dovrebbe fare altro, ma non ci interessa davvero la funzionalità 'CanExecute' che potresti salvaguardare facendo sì che' CanExecute' restituisca sempre true e sostituisca il gestore 'CanExecuteChanged' con implementazioni di allegati vuote (ad es. 'Evento pubblico EventHandler CanExecuteChanged {add {} remove {}} ') –

20

Oppure si potrebbe semplicemente aggiungere un pulsante con Annulla come testo e impostare IsCancel = True. Quindi Escape funzionerà come comando predefinito per chiudere.

+1

non è sempre l'ideale, ma mi piace ancora il suggerimento. Abbastanza semplice –

2

creare RoutedUICommand come qui di seguito

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

e aggiungerlo comando vincolante nel costruttore

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

Nessuno di sopra ha lavorato per me, tranne Kai di. Ho modificato la sua risposta: ho aggiunto "btn_close.IsCancel = true;" al costruttore. SettingsWindow è la mia seconda finestra e la finestra principale è (default) MainWindow.

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

Speranza che aiuta,

Simon S amore nia

0

Un altro modo possibile è quello di utilizzare proprietà associate

Bellow è un codice gist:

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

1

Su Window s mostrato con ShowDialog() è possibile utilizzare:

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

È anche possibile utilizzare PreviewKeyDown Evento

PreviewKeyDown="UserControl_PreviewKeyDown" 

codice dietro di voi chiamare comando di chiusura

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