2010-10-05 7 views
20

Gibt es eine einfache Möglichkeit, der gesamten WPF-Anwendung zu sagen, dass sie auf Escape-Tasten drücken soll, indem sie versucht, die gerade fokussierte Witwe zu schließen? Es ist keine große Mühe, die Befehls- und Eingabebindungen manuell einzurichten, aber ich frage mich, ob die Wiederholung dieses XAML in allen Fenstern der eleganteste Ansatz ist?Wie kann ich das Verhalten 'Bei Escape-Taste drücken' allen WPF-Fenstern innerhalb eines Projekts zuweisen?

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

Irgendwelche konstruktiven Vorschläge willkommen!

Antwort

30

Alles, was ich vorschlagen kann, um dies zu verbessern, ist die Notwendigkeit eines Event-Handlers durch Bindung an eine statische Befehlsinstanz zu entfernen.

Hinweis: Dies funktioniert nur in .NET 4 und erfordert die Fähigkeit, an die Eigenschaften KeyBinding zu binden.

zunächst einen Befehl erstellen, die ein Fenster als Parameter und ruft Close im Execute Methode:

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

Dann können Sie Ihre KeyBinding zum statischen Instance Eigenschaft binden:

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

Ich weiß nicht, dass dies notwendigerweise besser als Ihr Ansatz ist, aber es bedeutet marginal weniger Boilerplate an der Spitze jeder Window und dass Sie keinen Event-Handler in jede

+0

kann das dazu führen können, um Speicherlecks, da der Singleton einen 'EventHandler' hat? – Maslow

+0

Es sollte nicht funktionieren, aber die "CanExecute" -Funktionalität interessiert Sie nicht. Sie können dagegen "CanExecute" immer auf "True" setzen und den "CanExecuteChanged" - Handler durch leere Attachment-Implementierungen (zB 'public event EventHandler ') ersetzen CanExecuteChanged {add {} remove {}} ') –

20

hinzufügen müssen Oder Sie könnten einfach eine Schaltfläche mit Abbrechen als Text hinzufügen und IsCancel = True setzen. Dann funktioniert Escape als Standardbefehl zum Schließen.

+1

nicht immer ideal, aber immer noch wie der Vorschlag. Einfach genug. –

2

erstellen RoutedUICommand wie unten

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

und fügen Sie es

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

Keines der oben für mich gearbeitet, außer Kais in Konstruktor Befehlsbindung. Ich änderte seine Antwort: Ich fügte 'btn_close.IsCancel = true;' zum Konstruktor. SettingsWindow ist mein zweites Fenster und Hauptfenster ist (Standard) MainWindow.

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

Hoffe, dass es hilft,

Simon S Liebe nia

0

Eine weitere Möglichkeit angefügten Eigenschaften zu verwenden ist

Bellow ist ein Kern-Code:

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

1

Auf Window s mit ShowDialog() gezeigt Sie verwenden können:

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

Sie auch PreviewKeyDown Ereignis

PreviewKeyDown="UserControl_PreviewKeyDown" 

-Code hinter rufen Sie schließen Befehl

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