2017-11-25 7 views
1

Ich habe eine WPF-App mit MVVM erstellt und habe Schwierigkeiten beim Schließen/Öffnen von Fenstern. Auf meinem Anmeldefenster, verwende ich die folgende Methode die Login-Fenster und öffnen Sie das WindowOPHome Fenster mit einem Button-Klick, um zu schließen:WPF MVVM Fenster schließen

  WindowOPHome dashboard = new WindowOPHome(); 
      dashboard.Show(); 
      Application.Current.MainWindow.Close(); 

Alles funktioniert gut und das Login-Fenster schließt, während das WindowOPHome Fenster kann geöffnet werden. Wenn ich versuche, das WindowOPHome-Fenster zu schließen und das WindowMainAdmin-Fenster mit einem Klick ähnlich der Anmeldefenster-/WindowOPHome-Aktion zu öffnen, wird das WindowMainAdmin-Fenster für einen Bruchteil einer Sekunde geöffnet und verschwindet dann nicht mehr. Im Anschluss ist der Code für WindowOPHome und Öffnung WindowMainAdmin endet:

 WindowMainAdmin dashboard = new WindowMainAdmin(); 
     dashboard.Show(); 
     Application.Current.MainWindow.Close(); 

Jede Hilfe wäre sehr dankbar! Bitte lassen Sie mich wissen, wenn Sie weitere Code-Teile benötigen. Ich danke dir sehr!

Antwort

1

Ich würde vorschlagen, dass Sie das Fenster, das Sie schließen möchten, explizit schließen, anstatt anzunehmen, dass es das aktuelle Hauptfenster ist.

Mit MVVM es viele verschiedene Möglichkeiten gibt, es zu tun, können Sie eine angeschlossene Verhalten oder übergeben Sie das Fenster mit dem View-Modell über den Befehlsparameter wie folgt verwenden:

in die Schaltfläche XAML für die Ansicht:

CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" 

in der Befehl-Methode in der Ansicht Modell:

if (parameter is System.Windows.Window) 
{ 
    WindowMainAdmin dashboard = new WindowMainAdmin(); 
    dashboard.Show(); 
    (parameter as System.Windows.Window).Close(); 
} 

.
Alternativ können Sie alle Fenster iterieren, bis Sie die gewünschte gefunden haben.

foreach(Window window in Application.Current.Windows) { 
    if(window is WindowOPHome) 
    { 
     window.Close(); 
     break; 
    } 
} 

Vielleicht möchten Sie andere auf einem anderen Objekt überprüfen, als nur die erste dieser Art zu schließen, wenn Sie öffnen mehr als eine Instanz eines Fensters haben müssen.

Sie könnten sogar anpassen, dass es eine statische Close-Methode innerhalb jeder Fensterklasse ist.

+0

Perfect! Dies ist sehr einfach und ich kann mich für zukünftige Anwendungen anpassen, wie Sie gesagt haben, wenn ich andere Fenster halten muss und diejenigen auswählen muss, die ich schließen muss. Vielen Dank! – Progolfer79

1

Ich denke, wenn Sie das Admin-Fenster erstellen, betrachtet das Programm Ihr Admin-Fenster als Ihr aktuelles Hauptfenster und schließt es. Um dies zu vermeiden, können Sie das gewünschte Fenster explizit schließen. Ich empfehle, ein MainViewModel zu implementieren, um alle Ihre Windows zu verwalten. In diesem Beispiel wird davon ausgegangen, dass nur ein Fenster geöffnet sein soll.

In View (Any Window):

private void OnClose(object sender, RoutedEventArgs e) 
{ 
    //ICommand Implemnation that informs MainViewModel of UserInput 
    //In this case, the command ShowOPHome is an Enum 
    inputhandler.Execute(MyCommands.ShowOPHome); 
} 

In Ansichtsmodell:

BaseWindow dashboard; 
.... 
public void ShowWindow(MyCommands Param) 
{ 
    //Verify Parameter 
    .... 
    if(!(dashboard is null)) 
     dashboard.Close(); 
    switch(Param) 
    { 
     case MyCommands.ShowOPHome: 
      dashboard = new WindowOPHome(); 
      break; 
     case MyCommands.ShowMainAdmin: 
      dashboard = new WindowMainAdmin(); 
      break; 
    } 
    dashboard.Show(); 

} 

InputHandler:

public class Inputhandler : ICommand 
{ 
    ... 
    public class Execute(object Data) 
    { 
     ... 
      mainViewModel.ShowWindow(MyCommands.ShowOPHome); 
     ... 
    } 
    ... 
} 
1

Sie eine MVVM reine Lösung für dieses Problem schaffen kann ein Paar mit von Hilfsklassen

public static class ViewCloser 
{ 
    public static readonly DependencyProperty DialogResultProperty = DependencyProperty.RegisterAttached(
     "DialogResult", 
     typeof(bool?), 
     typeof(ViewCloser), 
     new PropertyMetadata(DialogResultChanged)); 

    private static void DialogResultChanged(DependencyObject target, DependencyPropertyChangedEventArgs args) 
    { 
     var view = target as Window; 

     if (view == null) 
      return; 

     if (view.IsModal()) 
      view.DialogResult = args.NewValue as bool?; 
     else 
      view.Close(); 
    } 

    public static void SetDialogResult(Window target, bool? value) 
    { 
     target.SetValue(DialogResultProperty, value); 
    } 
} 


public static class WindowExtender 
{ 
    public static bool IsModal(this Window window) 
    { 
     var fieldInfo = typeof(Window).GetField("_showingAsDialog", BindingFlags.Instance | BindingFlags.NonPublic); 
     return fieldInfo != null && (bool)fieldInfo.GetValue(window); 
    } 
} 

In der Anwendung zunächst eine Eigenschaft in der es in der Ansicht bindet

private bool? _viewClosed; 

public bool? ViewClosed 
{ 
    get { return _viewClosed; } 
    set { 
      _viewClosed = value); 
      RaisePropertyChanged("ViewClosed"); 
     } 
} 

dann

Ansichtsmodell erstellen, unsere Helfer-Klasse.

<Window x:Class=" 
     ... 
     vhelpers:ViewCloser.DialogResult="{Binding ViewClosed}" 
     ... 
     > 
0

Alle diese sind großartige Lösungen! Ich wählte cjmurphs Lösung, weil sie sehr einfach war (für meinen schwachen Verstand), und ich kann sie leicht für zukünftige Anwendungen anpassen. Siehe den unten aufgeführten Code. Danke nochmal, alle zusammen!

XAML

Command="{Binding BtnMainAdminPageGO}" 
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" 

WindowOPMainViewModel

private ICommand _btnMainAdminPage; 

    public ICommand BtnMainAdminPageGO 
    { 
     get 
     { 
      if (_btnMainAdminPage == null) 
      { 
       _btnMainAdminPage = new RelayCommand(param => this.BtnMainAdminPage(), null); 
      } 

      return _btnMainAdminPage; 
     } 
    } 

    private void BtnMainAdminPage() 
    { 
     WindowMainAdmin dashboard = new WindowMainAdmin(); 
     dashboard.Show(); 
     foreach(Window window in Application.Current.Windows) 
     { 
      if (window is WindowOPHome) 
      { 
       window.Close(); 
       break; 
      } 
     } 

    } 
+0

Stetig darauf Chef! Du hast die zwei Optionen, die ich dir gegeben habe, durcheinander gebracht. Übergeben Sie den Parameter an Ihre Befehl ausführen Methode und Sie müssen nicht die Windows-Sammlung durchlaufen. Wenn Sie den Relay-Befehl deklarieren, tun Sie Folgendes: new RelayCommand (param => BtnMainAdminPage (param), null); Ändern Sie dann die execute-Methode als private void BtnMainAdminPage (Objektparameter) {WindowMainAdmin dashboard = new WindowMainAdmin(); dashboard.show(); if (Parameter ist System.windows.Window) (Parameter als System.Windows.Window) .Close();} – cjmurph