2013-08-26 20 views
5

Ich habe ein AddClientViewModel, das von 2 Ansichten referenziert wird (AddClientView und SuggestedAddressesView). Die AddClientView ist ein Formular, das ein Feld für eine Adresse enthält. Das Formular hat einen Validierungs-Button, der die eingegebene Adresse mit Geocoding validiert. Wenn mehr als eine Adresse zurückgegeben wird, wird die SuggestedAddressesView geöffnet.Öffnen/Schließen Ansicht von ViewModel

Hier ist, wie ich es derzeit tue:

AddClientViewModel:

private void ValidateExecute(object obj) 
    { 
     SuggestedAddresses = new ObservableCollection<DBHelper.GeocodeService.GeocodeResult>(GeoCodeTest.SuggestedAddress(FormattedAddress)); 

     .... 

     if (SuggestedAddresses.Count > 0) 
     { 
      var window = new SuggestedAddressesView(this); 
      window.DataContext = this; 
      window.Show(); 
     } 
    } 

Hier ist der SuggestedAddressesView Konstruktor wo AddClientViewModel von ViewModelBase erbt

public SuggestedAddressesView(ViewModelBase viewModel) 
    { 
     InitializeComponent(); 
     viewModel.ClosingRequest += (sender, e) => this.Close(); 
    } 

Das andere Problem, das ich habe, ist, Wenn ich OnClosingRequest() von AddClientViewModel ... aufrufen, werden sowohl AddClientView als auch SuggestedAddressesView geschlossen. Ich weiß, dass dies geschieht, weil beide Ansichten auf dasselbe ViewModel verweisen. Das ist nicht das Verhalten, das ich will. Ich möchte in der Lage sein, jedes Fenster unabhängig zu schließen.

Öffnet eine View aus der MVVM-Struktur von ViewModel und wie würde ich in der Lage sein, Fenster unabhängig voneinander zu schließen?

Antwort

5

Sobald Sie UI-Elemente beziehen (in diesem Fall die Ansicht) von der VM, Sie gehen gegen vorgeschlagen MVVM-Richtlinien. Nur damit können wir wissen, dass das Erstellen des Window Objekts in der VM falsch ist.

So, jetzt auf Gleichrichtung dies:

  • Zum einen versuchen, eine 1 View zu halten < -> 1 VM in Ihrer Anwendung. Es ist sauberer und ermöglicht es Ihnen, Implementierungen mit der gleichen Logik sehr einfach zu wechseln. Das Hinzufügen mehrerer Ansichten zu derselben VM, auch wenn sie nicht "bahnbrechend" ist, macht sie nur schwerfällig.
  • So jetzt haben Sie AddClientView und SuggestedAddressesView mit ihrer eigenen VM. Groß!

Implementierung einer Ansicht öffnen/Schließen von der VM:

  • Da wir nicht die Ansicht Zugriff direkt von unserem VM (mit Standards erfüllen), können wir Ansätze verwenden, wie unter Verwendung eines Messenger (MVVM Light), EventAggregator (PRISM) und so weiter, um eine "Nachricht" von der VM an die Ansicht zu senden, wenn Sie eine Ansicht öffnen/schließen und die eigentliche Operation in der Ansicht ausführen müssen.
  • Auf diese Weise initiiert die VM die Nachricht und kann für die gleiche Operation in der Einheit getestet werden und verweist nicht auf UI-Elemente.

einen „Messenger“ -Verfahrens Ansicht offen zu handhaben:

  • Wie pro Ihre Logik ist es die AddClientViewModel die für müssten fragen die SuggestedAddressesView geöffnet werden.
  • So, wenn Sie SuggestedAddresses.Count > 0 erkennen, würden Sie eine Nachricht an die AddClientView senden, die es bittet, die SuggestedAddressesView zu öffnen.
  • In AddClientView.xaml.cs nach dem Empfang dieser Nachricht würden Sie tun, was Sie gerade in der VM tun. Erstellen Sie ein Objekt von SuggestedAddressesView und rufen Sie .Show() darauf an.
  • Ein zusätzlicher Schritt, den Sie im obigen Schritt hinzufügen würden, ist die Zuweisung des DataContext von SuggestedAddressesView als SuggestedAddressesViewModel.

Das ist es. Nun, was Sie haben, ist, wenn AddClientViewModel zeigt SuggestedAddressesView gezeigt wird, sendet es eine Nachricht an seine eigene Ansicht und die View-In-Turn erstellt und zeigt die SuggestedAddressesView. Auf diese Weise referenziert die VM keine Views und wir halten weiterhin MVVM-Standards ein.

einen "Messenger" -Verfahrens Ansicht zu handhaben schließen:

  • ein View Closing ist ziemlich einfach. Wenn Sie die Ansicht von der VM schließen müssen, senden Sie eine Nachricht an die eigene Ansicht, in der Sie aufgefordert werden, die Ansicht zu schließen.
  • Auf Empfang dieser Nachricht schließt die Ansicht ziemlich viel selbst über .Hide()/.Close() oder aber sonst wollen Sie vielleicht, um es loszuwerden.

Darin behandelt jede VM ihre eigenen View-Closing und Sie haben keine Abhängigkeiten miteinander verbunden.

Sie können this als Startpunkt verwenden Sie im Umgang mit „Nachrichten“ für diesen Ansatz zu führen. Es hat einen beigefügten Download, den Sie bekommen können und sehen, wie die Messenger funktioniert. Dies ist mit MVVM Light, wenn Sie es nicht verwenden oder verwenden Sie etwas anderes/Ihre eigene MVVM-Implementierung, verwenden Sie es als Leitfaden, um zu bekommen, was Sie brauchen.

+0

In Ordnung, das macht Sinn! Das Problem, das ich habe ist, dass ich die Informationen aus ** gesammelt möchten SuggestedAddressesView ** an die weitergegeben werden ** ** AddClientViewModel (daher, warum ich wurde mit dem 1 VM für 2 Views). Der Grund dafür ist, dass die in ** SuggestedAddressesView ** ausgewählte Adresse einem im ** AddClientViewModel ** definierten Client zugewiesen ist. – francisg3

+1

@ francisg3 schau auf den Beispiel Link, den ich gepostet habe. Wenn Sie das Beispiel dort bekommen, öffnet das zweite 'Fenster 'Modal/Non-Modal Informationen zurück zum MainWindow. Dies ist der Prozess, den Sie auch für Ihre Anforderung verwenden würden. Sie würden Messenger verwenden, um eine Nachricht zu senden (hier wird die Nachricht die Daten sein, die Sie von SuggestedAddressViewModel zu AddClientViewModel senden möchten) – Viv

0

können Sie RelayCommand verwenden, so dass Sie den Parameter wie folgt senden:

Command="{Binding CloseWindowCommand, Mode=OneWay}" 
CommandParameter="{Binding ElementName=TestWindow}" 

Durch diese verwenden Sie die einzelnen Ansichten schließen können.

Beispiel:

public ICommand CloseCommand 
    { 
     get 
     { 
      return new RelayCommand(OnClose, IsEnable); 
     } 
    } 

public void OnClose(object param) 
    { 
     AddClientView/SuggestedAddressesView Obj = param as AddClientView/SuggestedAddressesView; 
     obj.Close(); 
    } 
0

Zum Fenster von Ansichtsmodell öffnen:

erstellen NavigationService.cs Klasse für Fenster zu öffnen: NavigationService.cs Lassen

nun in dieser Klasse Datei folgenden Code setzen.

public void ShowWindow1Screen(Window1ViewModel window1ViewModel) 
     { 
      Window1= new Window1(); 
      Window1.DataContext = window1ViewModel; 
      Window1.Owner = Window1View; 
      Window1.ShowDialog(); 
     } 

dann. Erstellen Sie eine Instanz der NavigationService.cs-Klasse MainWindowViewModel-Datei. Dann

Window1ViewModel window1ViewModel = new Vindow1ViewModel(); 
window1ViewModel.Name = MainWindowTextValue; 
NavigationService navigationService = new NavigationService(); 
navigationService.ShowWindow1Screen(window1ViewModel); 
Verwandte Themen