2016-03-21 20 views
4

Wie kann ich Abbrechen von bestimmten Formular nach Abbrechen Schaltfläche (oder X in der oberen rechten Ecke, oder Esc) geklickt wurde abgebrochen?Wie Fenster schließen in MVVM WPF-Anwendung

WPF:

<Window 
    ... 
    x:Class="MyApp.MyView" 
    ... 
/> 
    <Button Content="Cancel" Command="{Binding CancelCommand}" IsCancel="True"/> 
</Window> 

Ansichtsmodell:

public class MyViewModel : Screen { 
    private CancelCommand cancelCommand; 
    public CancelCommand CancelCommand { 
    get { return cancelCommand; } 
    } 
    public MyViewModel() { 
    cancelCommand = new CancelCommand(this); 
    } 
} 

public class CancelCommand : ICommand { 

    public CancelCommand(MyViewModel viewModel) { 
    this.viewModel = viewModel; 
    } 

    public override void Execute(object parameter) { 
    if (true) { // here is a real condition 
     MessageBoxResult messageBoxResult = System.Windows.MessageBox.Show(
     "Really close?", "Warning", 
     System.Windows.MessageBoxButton.YesNo); 
     if (messageBoxResult == MessageBoxResult.No) { return; } 
    } 
    viewModel.TryClose(false); 
    } 

    public override bool CanExecute(object parameter) { 
    return true; 
    } 
} 

Aktuelle Code funktioniert nicht. Ich möchte, dass der Benutzer auf dem aktuellen Formular bleibt, wenn er im Popup-Dialogfeld "Nein" wählt. Auch das Überschreiben von CanExecute hilft nicht. Es deaktiviert nur die Schaltfläche. Ich möchte dem Benutzer erlauben, den Knopf zu drücken, aber dann ihm mitteilen, dass Daten verloren gehen. Vielleicht sollte ich einen Ereignis-Listener auf Knopf zuweisen?

EDIT:

I Popup-Managed zeigt auf Abbrechen. Aber ich kann immer noch nicht Esc oder X-Taste (oben rechts) verwalten. Es scheint, dass ich mit der Schaltfläche "Abbrechen" verwechselt wurde, weil die Execute-Methode ausgeführt wird, wenn ich auf die Schaltfläche "X" oder "Esc" klicke.

EDIT2:

änderte ich die Frage. Es war "Wie Abbrechen Cancel-Taste". Es war jedoch nicht das, wonach ich suchte. Ich muss die Esc- oder X-Taste abbrechen. In 'MyViewModel' ich hinzufügen:

 protected override void OnViewAttached(object view, object context) { 
      base.OnViewAttached(view, context); 
      (view as MyView).Closing += MyViewModel_Closing; 
     } 

     void MyViewModel_Closing(object sender, System.ComponentModel.CancelEventArgs e) { 
      if (true) { 
       MessageBoxResult messageBoxResult = System.Windows.MessageBox.Show(
        "Really close?", "Warning", 
        System.Windows.MessageBoxButton.YesNo); 
       if (messageBoxResult == MessageBoxResult.No) { 
        e.Cancel = true; 
       } 
      } 
     } 

Dies löste mein Problem. Ich brauche jedoch ICommand, um zu verstehen, auf welche Schaltfläche geklickt wurde, Speichern oder Abbrechen. Gibt es eine Möglichkeit, die Verwendung von Ereignissen zu eliminieren?

+3

Hat Ihr 'viewModel.TryClose (false)' Funktion ein Ereignis Ihrer Ansicht sendet den Dialog zu schließen? Wenn ja, können Sie 'IsCancel =" true "' aus dem XAML-Code entfernen. Dieser Teil bewirkt, dass das Formular geschlossen wird. –

+0

@ qqww2 Wenn ich IsCancel = "true" entferne, dann wenn ich Esc klicke, schließt es das Fenster nicht. Ich möchte, dass das Fenster auf Esc geschlossen wird. –

+1

Registrieren Sie eine 'KeyBinding' zu Ihrem Befehl. [Hier] (http://stackoverflow.com/questions/19697106/create-key-binding-in-wpf) ist ein Beispiel. –

Antwort

4

Sie versuchen, die Arbeit von View in der ViewModel-Klasse auszuführen. Lassen Sie Ihre View-Klasse die abschließende Anfrage verarbeiten und ob sie abgebrochen werden soll oder nicht.

Um das Schließen eines Fensters abzubrechen, können Sie das Ereignis Closing abonnieren und CancelEventArgs.Cancel auf true setzen, nachdem Sie eine MessageBox angezeigt haben. Hier

ein Beispiel:

<Window 
    ... 
    x:Class="MyApp.MyView" 
    Closing="OnClosing" 
    ... 
/> 
</Window> 

-Code hinter:

private void OnClosing(object sender, CancelEventArgs e) 
{ 
    MessageBoxResult result = MessageBox.Show("Really close?", "Warning", MessageBoxButton.YesNo); 
    if (result != MessageBoxResult.Yes) 
    { 
     e.Cancel = true; 
    } 

    bool shouldClose = ((MyViewModel) DataContext).TryClose(false); 
    if(!shouldClose) 
    { 
     e.Cancel = true; 
    } 
} 
+0

Das Problem hier ist, dass View nicht weiß, ob es geschlossen werden sollte oder nicht. Ich kann nicht sehen, wie ich auf ViewModel-Daten zugreifen kann. –

+0

Ok. Kannst du im Detail erklären, was der Algorithmus ist, um das Fenster zu schließen? –

+0

Ich ordne Handler in ViewModel dem OnClosing sogar zu. Wie ich es nach EDIT2 gesagt habe. In diesem Fall kann ich jedoch nicht unterscheiden, WIE es geschlossen wurde. Ich meine, ohne zusätzliche Flags, die ich in ICommand setzen werde. –