Laden...

View mit ViewModel verbinden

Erstellt von IamTheBug vor 8 Jahren Letzter Beitrag vor 8 Jahren 5.888 Views
I
IamTheBug Themenstarter:in
401 Beiträge seit 2006
vor 8 Jahren
View mit ViewModel verbinden

Hallo,

ich habe eigentlich eine kleine und einfache Frage zum Verbinden von View und ViewModel. Wie verbindet man diese am Besten bzw. was ist Best-Practice?
1: Das Verbinden direkt im XAML 2: Das View lädt in seinem Konstruktor das ViewModel und weisst es sich als DataContext zu. 3: Eine weitere Klasse erzeugt eine Instanz des Views und übergibt dem Konstruktor als Parameter das ViewModel. 4: Eine Andere Klasse erzeugt das View und das ViewModel und verbindet diese einfach mit View.DataContext = ViewModel.

Was ist eine gängige oder die sinnvolste Methode? Oder ist dies von Fall zu Fall unterschiedlich?

Meine Frage hat sich prinzipiell aus Folgender Situation ergeben:

Ich habe eine View das zwei TextFelder enthält. Als eine Art Ergebnis möchte ich ein "DialogResult" abfragen das den Inhalt beider TextFelder als ein Gesamtstring zurück gibt.

Die Funktion die dieses tut hätte ich gerne in das ViewModel gepackt.
Wenn jetzt eine Funktion das Vie erzeugt und lädt und das Viemodel nicht kennt so müsste ich ja im View eine GetDialogFunktion implementieren die dann die selbe Funktion im ViewModel abfragt. Das scheint mir doch etwas sinnfrei oder?

BeispielCode:


public void show()
{
  //hier passiert etwas
  DialogPlanung dialogPlanung = new DialogPlanung();
  dialogPlanung.ShowDialog();
  //die naechste Zeile ist fraglich
  dialogPlanung.GetDialogResult());
}


   public partial class DialogPlanung : Window
    {
        public DialogPlanung()
        {
            InitializeComponent();
            this.DataContext = new ViewModel();
        }

        public string GetDialogResult()
        {
         //return verbinde die beiden txtFelder oder
         //return Viewmodel.GetDialogResult();
        }
  }

Mfg

IamTheBug

16.835 Beiträge seit 2008
vor 8 Jahren

Best Practise ist der MVVM Pattern. WPF ist darauf ausgelegt.

I
IamTheBug Themenstarter:in
401 Beiträge seit 2006
vor 8 Jahren

Hi,

aus der Antwort geht für mich jetzt keine explizite Lösung hervor. Ich verwende doch das MVVM Pattern. Ich habe das doch oben beschrieben und gesagt das ich ein View und ein ViewModel verwenden. Die Frage war aber wie die beiden am Besten miteinander bekannt gemacht werden sollen.

Viele Grüße

Mfg

IamTheBug

3.003 Beiträge seit 2006
vor 8 Jahren

Ohne Code-Behind. Wenn du MVVM machst und den Code-Behind deines Views aufrufst, machst du in den meisten Fällen was verkehrt.


<Window.DataContext>
     <myns:myviewmodel />
</Window.DataContext>


//vollständiger code-behind:
  public partial class DialogPlanung : Window
    {
        public DialogPlanung()
        {
            InitializeComponent();
        }
  }

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

I
IamTheBug Themenstarter:in
401 Beiträge seit 2006
vor 8 Jahren

Ok, das versuche ich dann mal so.

Und der oben beschriebene Fall das es eine Klasse gibt die vom View eine Instanz bildet und diese per showDialog() anzeigt? Wie erhalte ich nach dem der Dialog geschlossen wurde Zugriff auf das ViewModel um dort eine Methode für einen Rückgabewert abzufragen? Muss ich da über den DataContext des Views gehen oder geht das auch schöner?

Mfg

IamTheBug

2.207 Beiträge seit 2011
vor 8 Jahren

Hallo IamTheBug,

kann man über ein Command lösen, was dir einen Dialog öffnet. Nach dem Schliessen des Dialogs verarbeitest du den Rückgabewert einfach entsprechend.

Gruss

Coffeebean

4.939 Beiträge seit 2008
vor 8 Jahren

Hallo,

du solltest bei MVVM nur im ViewModel Code haben und dieser sollte auch nur mit anderen ViewModels kommunizieren (d.h. niemals eine View direkt aufrufen o.ä.).
Das Stichwort, mit dem sich ein Aufruf eines Views (indirekt) aus einem ViewModel heraus gestalten läßt, heißt "DialogService", s. z.B. Showing Dialogs When Using the MVVM Pattern oder Good or bad practice for Dialogs in wpf with MVVM?.

I
IamTheBug Themenstarter:in
401 Beiträge seit 2006
vor 8 Jahren

Hallo,

du solltest bei MVVM nur im ViewModel Code haben und dieser sollte auch nur mit anderen ViewModels kommunizieren (d.h. niemals eine View direkt aufrufen o.ä.).

Das ist mir schon klar und das ist ja auch in meinem Fall so. Das ViewModel ruft NICHT seinen eigenen View auf. Auch ruf kein anderes ViewModel das View auf. Das View wird einfach in einer Main-Klasse geladen und angezeigt. Dies main-klasse ist der Einstieg in das"Programm". Dies befindet sich in einer dll und wird durch ein anderes Programme geladen.

Ich lese mal die beiden von dir verlinkten Artikel, eventuell ist ja etwas für mich dabei.

Viele Grüße

Mfg

IamTheBug

5.299 Beiträge seit 2008
vor 8 Jahren

Das View wird einfach in einer Main-Klasse geladen und angezeigt. Dies main-klasse ist der Einstieg in das"Programm". Dies befindet sich in einer dll und wird durch ein anderes Programme geladen. ist ein bischen verwirrend, aber mir scheint erkennbar, dass was faul ist.

Aber zunächstmal die Verwirrung:
"Dies befindet sich in einer dll und wird durch ein anderes Programm geladen"?? Was ist "dies"?

nun was faul scheint:
"Das View wird einfach in einer Main-Klasse geladen und angezeigt."
Also vorgesehen ist, dass das View in app.xaml geladen und gestartet wird - in keiner anderen Klasse sonst.

Kann natürlich sein, dass du iwie besondere Anforderungen hast, aber du frugst ja nach Standard-Vorgehensweisen.

Und da hat man halt die App.Xaml, und darin ist das StartupWindow definiert, und da gibts auch eine Resource mit dem Root-Viewmodel.

Der frühe Apfel fängt den Wurm.

1.040 Beiträge seit 2007
vor 8 Jahren
  
<Window.DataContext>  
     <myns:myviewmodel />  
</Window.DataContext>  
  

Dazu hätte ich mal eine Frage:
Ich bin damals aus der WinForms-Welt in meiner aktuellen Firma ins kalte "WPF-Wasser" geworfen worden, hier wird der DataContext im Codebehind gesetzt.
Die von dir genannte Lösung funktioniert bei ViewModels mit einem parameterlosen Konstruktor, wie ist aber der "Best Practice" bei Konstruktoren mit Parametern?

Also vorgesehen ist, dass das View in app.xaml geladen und gestartet wird - in keiner anderen Klasse sonst.
...
Und da hat man halt die App.Xaml, und darin ist das StartupWindow definiert, und da gibts auch eine Resource mit dem Root-Viewmodel.

Es ist auch möglich eine App.cs anzulegen. Wir verwenden hier z.B. keine App.xaml zum Starten unserer Programme.

3.003 Beiträge seit 2006
vor 8 Jahren

Dazu hätte ich mal eine Frage:
Ich bin damals aus der WinForms-Welt in meiner aktuellen Firma ins kalte "WPF-Wasser" geworfen worden, hier wird der DataContext im Codebehind gesetzt.
Die von dir genannte Lösung funktioniert bei ViewModels mit einem parameterlosen Konstruktor, wie ist aber der "Best Practice" bei Konstruktoren mit Parametern?

Gute Frage. Meine erste spontane Reaktion wäre "Injection", meine zweite, weniger spontane Reaktion wäre, dass ViewModels generell keine Parameter im Konstruktor haben sollten. Warum sollte ein ViewModel von irgend etwas abhängig sein?

Sie tun nichts weiter, als das Verhalten des Views zu modellieren - Parameter weisen (nach meiner Meinung) auf ein Designmanko hin; sehr wahrscheinlich auf eine inkorrekte Trennung zwischen VM und M. Vermutlich würde ich dieses Manko ggf. hinnehmen, wenn ich dadurch ein bisschen Flexibilität gewinnen kann.

(Möglich wäre auch - dritte Reaktion - eine DP am ViewModel, aber das halte ich nicht für sehr sauber.)

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

F
10.010 Beiträge seit 2004
vor 8 Jahren

dass ViewModels generell keine Parameter im Konstruktor haben sollten. Warum sollte ein ViewModel von irgend etwas abhängig sein?

Wo soll die VM denn das Model herbekommen? Oder den Service zum speichern, schalten Navigieren usw?

Das ist ja der Grund warum VM's eigentlich per Container erzeugt werden sollten.

5.299 Beiträge seit 2008
vor 8 Jahren

Also vorgesehen ist, dass das View in app.xaml geladen und gestartet wird - in keiner anderen Klasse sonst.
...
Und da hat man halt die App.Xaml, und darin ist das StartupWindow definiert, und da gibts auch eine Resource mit dem Root-Viewmodel.

Es ist auch möglich eine App.cs anzulegen. Wir verwenden hier z.B. keine App.xaml zum Starten unserer Programme. ja schön und gut. Jo, in Wpf kann man alles auch ganz anders machen und hat immer zig Möglichkeiten.

Mir ist jdfs aufgefallen, dass es einen Property App.StartupUri gibt, die man im app.Xaml setzen kann.
Daher hätte ich es für eine Standard-Vorgehensweise gehalten, das auch zu tun (und einfach ists obendrein).
Aber das ist offensichtlich vollkommen naiv von mir, und iwas mit Containern, Injection, und eine App.cs ohne Xaml ist viel besser - app.Xaml und den StartupUri hat MS nur erfunden, um uns zu verwirren und vom rechten Weg abzubringen.

Der frühe Apfel fängt den Wurm.

1.040 Beiträge seit 2007
vor 8 Jahren

Hast du heute deinen schlechten Tag? 🤔
Das war lediglich ein Hinweis, dass es noch einen anderen Weg gibt. Grade was Fehlerhandling der Applikation angeht ist die App.xaml nicht wirklich zu gebrauchen.

EDIT: Das mit der Injection bezieht sich zudem auf eine ganz andere Frage.

16.835 Beiträge seit 2008
vor 8 Jahren

Unabhängig davon, dass der Umgang netter sein könnte bitte ich euch endlich [Hinweis] Wie poste ich richtig? "2.3 Sparsam zitieren, keine Full Quotes" zu beachten.
Keine Lust, dass ich dauernd die Beiträge editieren muss 😉 Ihr seid doch lang genug dabei..
Danke!

5.299 Beiträge seit 2008
vor 8 Jahren

[schlechter Tag]

hmm - ja, iwie schon, aber egal.
ich vermute halt, den TE wird so eine Beratung in alle Richtungen gleichzeitig nicht wirklich weiter bringen.
Aber alles was ich beitragen kann, wäre auch nur eine weitere Richtung, also ich klink mich daher jetzt aus, es sei denn, der TE ist nu speziell an "meiner Richtung" noch besonders interessiert (etwa weil die anderen iwie doch nicht ausreichen).

Der frühe Apfel fängt den Wurm.

1.040 Beiträge seit 2007
vor 8 Jahren

@ErfinderDesRades:
Mich würde deine Vorgehensweise bzgl. ViewModels schon interessieren (unabhängig von App.xaml oder App.cs 😉): wie löst du es, wenn du Konstruktorparameter hast? Wenn ich jetzt richtig quer gelesen habe, machst du es ja so wie LaTino.

EDIT: Wir hier machen es derzeit so:

2: Das View lädt in seinem Konstruktor das ViewModel und weisst es sich als DataContext zu.

709 Beiträge seit 2008
vor 8 Jahren

Hallo,
ich möchte nun auch mal einen Ansatz vorstellen.

Ich nutze eine Klasse DialogService, über die jede View erzeugt wird.
Beim Service werden zu Beginn die View- und die dazugehörigen ViewModel-Typen registriert.
Danach erstellt man - wo und wie auch immer - ein ViewModel-Objekt und übergibt das der entsprechenden Methode des DialogService.
Dieser ermittelt anhand des ViewModel-Typen den View-Typen, erzeugt ein Objekt davon, weist dem DataContext das übergebene ViewModel-Objekt zu und zeigt die View an.

Das erste Fenster wird über den Service in der App.cs erzeugt.

Gruß
Micha

3.003 Beiträge seit 2006
vor 8 Jahren

dass ViewModels generell keine Parameter im Konstruktor haben sollten. Warum sollte ein ViewModel von irgend etwas abhängig sein?

Wo soll die VM denn das Model herbekommen? Oder den Service zum speichern, schalten Navigieren usw?

Das ist ja der Grund warum VM's eigentlich per Container erzeugt werden sollten.

Ah, schlecht von mir formuliert. Lies: "Warum sollte die Erzeugung eines Viewmodels von irgend etwas abhängig sein."

Ich sehe den Widerspruch nicht, bzw nicht so absolut. IoC/DI erfordert an keiner stelle parametrisierte Konstruktoren. Es wird nur gern verwendet - vermute mal, weil der IoC-Hypetrain von Java aus losgerollt ist und es dort nunmal die einzig praktikable Variante ist, DI per constructor injection zu realisieren. (Ich hasse mich gerade selber für das Bullshit-Bingo. Lose Kopplung, realisiert mit Strategiemustern. Ach, auch nicht besser.

p!lle, eine weitere Situation, wo das Viewmodel nicht deklarativ festgelegt werden kann, sind viewmodel-first-Konzepte (wenn der view erst erzeugt wird, kann ich nicht deklarativ das vm festlegen, ist logisch). Ist 'ne andere Geschichte und kann sicherlich Vorteile haben. Ich bin bei WPF noch mit keinem Konzept an den Punkt gelangt, wo ich mir eine grundsätzlich andere Organisation der ViewModels und Views gewünscht hätte. Hängt von der Situation ab, und abhängig davon, wie man sich entscheidet, ist dann eben auch die "best practice" für die Erzeugung der Kopplung zwischen VM und V.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

F
10.010 Beiträge seit 2004
vor 8 Jahren

IoC/DI erfordert an keiner stelle parametrisierte Konstruktoren.

Haben wir da wieder diese leidliche Diskussion was DI/IOC und was ServiceLocator ist?

@pinki
Es gibt View-First und ViewModel-First.
Du machst ViewModel First ( wie z.b. Caliburn.Micro ) und brauchst da also ( wenn du es so machst ) einen View-Locator.

Die meisten "einfachen" MVVM Implementationen sind View-First, da arbeitet man dann ( wenn ) mit einem ViewModel-Locator.

Das sind Namen ( nicht mehr nicht weniger ) die man so in der "Gemeinde" findet.
Bevor man eigene Namen kreiert sollte man sich anschauen was es so gibt, dann redet man nicht aneinander vorbei, und muss vor allem nicht ständig das Rad Selber erfinden.

3.003 Beiträge seit 2006
vor 8 Jahren

Haben wir da wieder diese leidliche Diskussion was DI/IOC und was ServiceLocator ist?

Keine Ahnung, offenbar habe ich bisherige Diskussionen dazu verpasst 😉. Ich denke mal, es herrscht aber Einigkeit, dass dieses Thema für 95% der MVVM-Fragen hier im Forum sowieso irrelevant ist. Sollte man bei der Entwicklung einer komplexeren Applikation feststellen, dass man besser eine Architektur einführt, die auf irgendeine Weise Views und Viewmodels organisiert, dann hat man vermutlich auch genug Erfahrung, um seine Anforderungen präzise zu formulieren und dementsprechend etwas aussuchen zu können.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

I
IamTheBug Themenstarter:in
401 Beiträge seit 2006
vor 8 Jahren

Hallo,

Vielen Dank erstmal für die rege Beteiligung zu meiner Frage 😁
Ich bin die Tage unterwegs und nicht an meinem Computer. Deshalb kann ich nur an meinem Handy kurz mitlesen und antworten.
Wenn ich zurück bin werde aber mal all eure Informationen durcharbeite.

Ich will nur noch einmal kurz meine Situation aufgreifen die ich kurz beschrieb bevor andere hier diskutiert haben 🙂

Also meine erste Frage war ja das Verbinden von View und ViewModel. Ich denke das hat sich erledigt.

Der zweite Teil der wohl etwas zur Verwirrung beigetragen hat war folgendes.
Ich habe im Visual Studio als Startprojekt keine WPF Anwendung gewählt sondern eine dll.
Die Anwendung ist nämlich ein Plugin für eine andere Anwendung. Diese Anwendung lädt die dll
Und erwartet eine Methode namens show(). Darin kann ich mich austoben. Also erstelle ich dort eine Instanz eines WPF Fensters und zeige dieses per ShowDialog() an. Soweit ist doch alles ok. Da kann ich ja nicht anders herangehen, wenn die Pluginschnittstelle so ist. (Denn weiter oben meinte jemand das sei schon faul).
Wenn jetzt der Dialog geschlossen wird dann wollte ich irgendwie an den Inhalt der Textfelder ran kommen und da stellte sich mir eben die Frage was das beste ist. Denn das Ergebnis muss über das Plugin an das Programm zurück geschickt werden.

Oh man. Jetzt ist hier wieder viel Text draus geworden. Ich hoffe es ist klar und nicht verwirrender geworden 🙂

Vielen Dank und viele Grüße

P.S. Vielen Dank für die Links "wie rufe ich einen Dialog aus einem Dialog unter WPF auf" das war sehr informativ.

Mfg

IamTheBug

5.299 Beiträge seit 2008
vor 8 Jahren

@ErfinderDesRades:
Mich würde deine Vorgehensweise bzgl. ViewModels schon interessieren Also wie ich oft anfange, hab ich hier mal erläutert:
https://www.vb-paradise.de/index.php/Thread/115475-MVVM-Anwendungs-Struktur/?postID=1005812
Also ich hab ein MainViewmodel, wo meist (nicht immer) alle Viewmodels zusammenfließen, und als Properties enthalten sind. Das sind dann garnet so viele, weil was da zusammenfließt kann ebenfalls wieder komplex aufgebaut sein, also zB ein MainViewmodel mag mit 2 - 3 Workspaces schon ziemlich viel abdecken.
Der MainViewmodel-Konstruktor ist parameterlos.

Wie gesagt: So mach ich das oft, und was dabei rauskommt, sieht mir oft auch sehr kompakt, übersichtlich und plausibel aus.
Natürlich erfüllt es nicht alle Ansprüche aller Szenarien, die es geben kann, aber oft genug passt es eben doch auch sehr gut.

Der frühe Apfel fängt den Wurm.