2008-11-19 4 views
17

Ich habe gerade angefangen, M-V-VM für eine WPF-Anwendung zu untersuchen. Bis auf dieses spezielle Problem macht alles bisher Sinn ...M-V-VM Designfrage. Aufruf von ViewModel

Ich habe ein ViewModel Ich rufe Suche an. Dieses ViewModel bindet an ein Datagrid und listet Ergebnisse von Elementen auf. Jetzt habe ich einen Befehl, der eine andere Ansicht, die Details des Einzelteils bringen muss.

Die Logik zum Anzeigen einer anderen Ansicht in der Suchansicht scheint nicht richtig zu sein, sie ist überhaupt nicht testbar.

Hier ist mein Viewmodel-Implementierung, die ...

public class SearchViewModel 
{ 
    public void SelectItem() 
    { 
    // I want to call the DetailsView from here 
    // this seems wrong, and is untestable 
    var detailsView = new DetailsView(); 
    detailsView.Show(); 
    } 
} 

Wo die Logik eine Ansicht von einer Viewmodel-Methode nicht prüfbar ist in diesem Muster gehen zu zeigen?

Antwort

12

Ansichten sollten niemals irgendwo unterhalb der UI-Ebene instanziiert werden. VMs existieren unterhalb dieses Bereichs, daher ist dies nicht der Ort, um diese Logik zu setzen (wie Sie bereits erkannt haben).

Es wird fast immer ein Ereignis auf Benutzerebene geben, das anzeigt, dass die Ansicht erstellt werden muss. In Ihrem Beispiel könnte es sich um ein Zeilen- (Doppel-) Klick-Ereignis auf dem Datagrid handeln. Das wäre der richtige Ort, um das DetailsView-Fenster zu öffnen und anzuzeigen.

+0

Danke für die Hilfe, das scheint wie eine praktikable Lösung. Auch wenn ich die Logik zum Einrichten der Ansicht nicht Unit-testen kann (Festlegen von Eigenschaften, die mit dem injizierten ViewModel interagieren), lassen sich die ViewModels testbar, wo sich der Großteil der Logik befindet. – Jab

+1

Wenn ein einfaches Ereignis die Ansicht öffnet, ist das gut. Aber was, wenn das Ereignis mehr Aktion, Datenabruf, Verifizierung benötigt. Würdest du das Zeug auch in den Blick nehmen? Oder eine andere Ebene der Indirektion schaffen? – Sam

+0

In der Tat. Die gleiche Frage wie Sam hier drüben. Was ist, wenn Sie vor dem Öffnen der Ansicht mehr Daten oder Logik benötigen? (Bsp. wenn Eigenschaft x = 1 offene Sicht 1, wenn Eigenschaft x = 2 andere Sicht öffnen) –

0

Wir verwenden eine Variante für dieses Muster. Hier haben wir Controller, die die VM darstellen. Der Datenkontext der View ist also die VM und unsere DTOs sind Eigenschaften der VM/Controller. Wir nennen es immer noch einen Controller, da wir dies als Kontrollpunkt verwenden und somit bestimmte Befehle aus der Ansicht übernehmen. Dies ist (denke ich), wo wir den Befehl wie Ihren implementieren würden.

18

Wie Kiff bemerkt:

Ansichten sollten nie irgendwo "unterhalb" der UI-Ebene instanziert werden. VMs existieren unterhalb dieses Bereichs, daher ist dies nicht der Ort, um diese Logik zu setzen (wie Sie bereits erkannt haben).

Es wird fast immer einige UI Level-Ereignis, das die müssen die Ansicht erstellen müssen. In Ihrem Beispiel könnte es eine Zeile sein (Doppel) klicken Ereignis auf das Datagrid. Das wäre der Ort, um New-up und zeigen Sie Ihre DetailsView-Fenster .

Sie müssen erkennen, dass M-V-VM ist etwas anders als andere Muster wie MVC oder MVP. Das ViewModel hat keine direkten Kenntnisse der Benutzeroberfläche. Das Öffnen einer anderen Ansicht ist eine sichtspezifische Funktion. Das Ansichtsmodell sollte weniger darauf achten, welche oder wie viele Ansichten seine Daten verwenden. Ich würde die Ansicht wahrscheinlich nie über einen Befehl öffnen.

alt text http://blogs.msdn.com//johngossman/attachment/576163.ashx

+0

Danke für die Klarstellung. – Jab

4

Hier ist eine Faustregel zu diesem Thema.

  • Wenn Sie lokale Aktionen in Ihrer Ansicht Handhabung sind, können Sie aus dem View-Modell intiate.

  • Wenn es sich um eine Queransicht handelt (z. B. um einen Suchbildschirm anzuzeigen), verwenden Sie entweder ein EventAggregator-Muster (einen Eventing-Dienst) oder einen Application Controller, auf den Sie Methoden anwenden, und es wird die Suche angezeigt.

1

Catel umfasst einen Ansatz, der die Verwendung von IUIVisualizerService beinhaltet. Diese Schnittstelle definiert einen UI-Controller, der zum Anzeigen von Dialogen in modaler oder modaler Form von einem ViewModel verwendet werden kann. Im Wesentlichen erstellen Sie innerhalb des übergeordneten vm das Ansichtsmodell, das hinter der neuen Ansicht bleiben soll, und der Dienst findet den zugehörigen (basierend auf einer Konvention oder Registrierung) und zeigt ihn dann an.