MVVM Umsetzung mit WinForms

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 165 Antworten in diesem Thema. Der letzte Beitrag () ist von Haudruferzappeltnoch.

    MVVM Umsetzung mit WinForms

    Moin moin

    Ich beschäftige mich soeben mit dem "Winform - MVVM". :S
    Das erste was mir beim lesen von vielen Beträgen aufgefallen ist, das man dabei erheblich mehr Code & Classes benötigt?
    Ich habe mit mal daran versucht und stelle fest, das es für mich nicht gerade "einfacher" ist damit zu arbeiten. Aber vielleicht habe ich das ganze auch falsch verstanden.

    In meinem Beispiel, werden Programmeinstellungen in eine XML-Datei geschrieben, die dann Programmweit abrufbar sein sollen.
    Dazu habe ich im Designer ein DS / DT erstellt, auf dem Form die ganzen Controls gesetzt und diese dann an die Bindingsource gebunden.

    Dazu eine Klasse ( A ) erstellt, welche die Daten aus der XML-Datei ausliest und in die definierten Property lädt.
    Dazu eine weitere separate Klasse ( B ) zum Laden der Daten aus den Property in die Bindingsource zum anzeigen auf dem Form. Des weiteren werden in der selben Klasse ( B ) die Daten gespeichert, von dem was in den Controls geändert wird.

    Auf der Form-Class die Bindungen an die Klassen A & B und noch Code der z.B. steuert, wenn CheckBoxen aktiviert werden, bestimmte Validierungen usw..

    Wenn ich das mit dem MVVM richtig verstehe, muss ich noch eine Klasse ( C ) mit "Property" für die einzelnen Controls des Forms erstellen :?: Und dann wieder zurück zur Form-Class :?:
    Ist das nicht ein wildes " von Klasse zu Klasse springen " ?( ?(
    Ich bekomme das Gefühl, das ich dabei den Überblick total verliere :S
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Du hast beim MVVM Pattern ein Ebene mehr hätte ich gesagt, aber irgendwie auch nicht.

    Die Modelebene beinhaltet alle Klassen die für die Daten relevant sind. Da kommt sozusagen das Auto hin.

    Die Viewebene, das ist das Form, da wird in der Regel bei MVVM nicht mehr gecodet, nur noch designed und das auch noch per Xaml-Code. Hier kann ein Autohersteller klicken und tippen um Einstellungen am Auto vorzunehmen.

    Dazwischen gibt es eine Bindingebene das sogenannte Viewmodel, also ein Model für die Steuerung der Form/ des Views. Etwas ähnliches macht eine Bindingsource zwischen DataSet und DataGridView. Hier wird das Geklicke und Getippe vom Autohersteller empfangen umgewandelt und an das Auto übertragen.

    So heißt MVVM: Model, View, Viewmodel.

    PS: DS und DT funktionieren in MVVM nicht. Was im DataTable eine Autozeile ist, wird in MVVM als tatsächliches Auto repräsentiert. Mehr oder minder baut man die Zeile selbst. Im Resultat macht es kaum einen Unterschied, nur der Designer fällt weg.
    Mit MVVM fängst du besser mit einem neuen Projekt an. Und versuchst nicht ein bestehendes Projekt auf MVVM umzumünzen.

    Amelie schrieb:

    Ich beschäftige mich soeben mit dem "Winform - MVVM".
    Das erste was mir beim lesen von vielen Beträgen aufgefallen ist, das man dabei erheblich mehr Code & Classes benötigt?
    Ich habe mit mal daran versucht und stelle fest, das es für mich nicht gerade "einfacher" ist damit zu arbeiten. Aber vielleicht habe ich das ganze auch falsch verstanden.
    Ich kenne deine Quellen ("vielen Beträge") nicht, aber "Winform - MVVM" - ich glaub, das ist eine Schnaps-Idee.
    WinForms ist für MVVM nicht ausgelegt, und da scheint mir naheliegend, dass es einen Riesen-Murks gibt, wenn man trotzdem versucht, mit WinForms eine Architektur aufzubauen, die man "MVVM" nennen kann.

    Wenn du dich für Architektur interessierst: Bei mir hat sich schon seit langem eine Standard-Architektur herausgebildet, die ich bei jedem Projekt erfolgreich anwende:
    • ein typisiertes Dataset ist mein Datenmodell
    • BusinesLogik lege ich in partialen Klassen an, die das Dataset erweitern
    • Vom typDataset gibts nur eine Instanz, sodass alle Forms/UserControls aufs selbe Dataset zugreifen
    • Ganz viel Databinding, über BindingSources.
    • Dazu kommt ein umfangreiches Helpers-Framework, welches viele Umständlichkeiten einfach macht.
    Wenn ich wollte, könnte ich das als "Windows-MVVM" verkaufen, wobei das Dataset Model und Viewmodel in einem ist.
    Aber ich habe damit schon gearbeitet, bevor es Wpf gab.

    Wenn wolle könnte ich dein Wetterstationen-Dingens in meine Architektur überführen.
    Auch könnte ich ein paar Artikel benennen, wo du diesen Pattern auch immer wiederfindest.
    @ErfinderDesRades

    Ich habe mal mein kleines Übungsprojekt angehangen.( ohne obj & bin )

    Mit "partialen klassen" habe ich auch schon mal etwas gemacht. Für kleine Projekte kam ich gut damit zurecht. Irgendwann aber blähten die sich immer weiter auf und ich verlor wieder den durchblick.
    "Vom typDataset gibts nur eine Instanz"
    Ja da habe ich oft so meine Probleme mit.

    ..in meine Architektur überführen .. Auch könnte ich ein paar Artikel benennen
    Artikel zum Lesen immer GUT ;)
    Das mit dem überführen, klingt gut aber ich muss es ja auch verstehen ;)

    @Haudruferzappeltnoch
    Die Wpf mit dem Xaml ... Das ist mir dann doch wieder viel zu viel. Frage mich, warum das nun wieder nochmal auseinander gestückelt wurde und wieder in einer anderen "Sprache" geschrieben werden muss.
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Amelie“ ()

    Amelie schrieb:

    Die Wpf mit dem Xaml ... Das ist mir dann doch wieder viel zu viel. Frage mich, warum das nun wieder nochmal auseinander gestückelt wurde und wieder in einer anderen "Sprache" geschrieben werden muss.


    Wirklich als "Sprache" würde ich XAML nicht bezeichnen. Das es abgekapselt ist, ist doch wunderbar. Jemand der "programmiert" und jemand(ein Designer) der sich ums UI kümmert und das so schon ganz einfach.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    natürlich ist Xaml eine Programmiersprache: "Extensible Application Markup Language".
    Und auch eine nicht einfach zu erlernende - weil tickt komplett anders.
    Xaml ist eine sog. "deklarative Sprache", also man kann damit keine Abläufe aufschreiben, sondern nur irgendwas mit irgendwem in Beziehung setzen.
    Also während man im prozeduralen VB aufschreibt, was wann in welcher Reihenfolge passieren soll, kann man Xaml eher als eine "Bildbeschreibung" auffassen.
    Und das ist grundsätzlich ziemlich pfiffig, die (Bild)beschreibung des GUIs zu trennen von dem, was es an Abläufen bei den Daten gibt.
    (Allerdings hätte ich mir als Sprache was anderes gewünscht als einen Xml-Dialekt - das ist doch lausig zu lesen und zu schreiben, und den Editor hätten sie auch um Welten besser machen können)
    Sql ist keine deklarative Sprache, sondern ist mengen-orientiert.
    wenn wolle lies Wiki: de.wikipedia.org/wiki/Deklarative_Programmierung


    @Amelie: Dein Codebeispiel ist zu wenig - daran kann man keine Architektur dran vorführen.
    Es sollten schon mehrere Datensätze zu lesen, zu ändern, zuzufügen, zu löschen und zu speichern sein.
    Ich könnte auch einfach dein Stationen-Dingens nehmen - das tut ja genau das.
    Soll ich?
    Also würdest du da noch durchblicken?
    Poste am besten ein Stationen-Dingens, wo du noch durchblickst.
    Gerne das, was ich schon bearbeitet habe, wenn das für dich ok ist.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ErfinderDesRades“ ()

    @ErfinderDesRades

    Moin moin

    Hab mal das Project angehangen. Im ZipFIle Daten von 2 Monaten.
    Habe da schon etwas weiter gemacht. Menu / Verwaltung ==> Einstellungen. Da funktioniert nach ersten Tests alles.

    --
    Das Xaml erinnert mich ein bissel an "HTML" wie für Webseiten..
    Naja vielleicht komme ich, wenn es "Windows24" gibt auch dahin. :D
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Amelie“ ()

    Jo, hab das ding nu teilweise überarbeitet.
    Es gibt nu einen Ordner GUI, da sind Forms und UserControls drin.
    Mein konzept ist, für jede TabPage ein eigenes UserControl, weil sonst wird das MainForm zu voll.

    Und einen Ordner Dataset, darin das Dataset, SampleDateien, Busineslogik.
    Printing habich auch der BL zugeschlagen, in einer eigenen Partial-Datei.
    Berechnungen sind natürlich Busineslogik.

    Ausserdem habich ein Helpers-Projekt hinzugefügt, mit minimalem Funktionsumfang.

    Ich habe mich nur um Laden, Speichern, Anzeigen, Drucken gekümmert.
    Die Sachen mit den "Settings" nicht angefasst - wäre schon sehr sinnvoll, wenn Settings auch ins selbe Dataset kämen.

    Sehr problematisch ist, dass dein Dataset keine Station-Tabelle hat.
    Da hab ich jetzt was nachgebessert, aber weil die BeispielDateien nur Messwerte (von Stationen) enthalten, nicht aber die Stationen selbst - daher ist das bischen krückelig geworden.
    Dateien
    • ClimaSenceE02.zip

      (191,54 kB, 43 mal heruntergeladen, zuletzt: )
    @ErfinderDesRades

    DANKE :)
    Ich werde mir deine Code dann mal genau ansehen und studieren.

    Das mit den getrennten Datasets für Daten und Einstellungen habe ich extra so gemacht, weil ich auch das mal gelesen habe, das man das trennen soll !?

    Was meinst du mit Daten von den Stationen selbst??
    Was mir schwerfällt, die Zuordung "Geschäftslogik und BuisenesLogik".
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Bewegen wir uns noch beim Thema MVVM in WinForms oder bist Du davon gedanklich weg? MVVM in WinForms ist ab .NET 7 dank CommandBinding schon recht gut umsetzbar, auch wenn @loeffel klargemacht hat, dass es noch weiter ausgebaut wird, um einen leichteren Übergang von ClassicWinForms (EventHandler etc.) zu WPF+MVVM zu ermöglichen, ohne gleich alles neuschreiben zu müssen. Aber es ist eben eine Umstellung, die so abläuft, dass man u.a. aus der FormKlasse alles entfernt, was nicht pur GUI-manipulierender Code ist. DataBinding wird da eben nochmal intensiver eingestellt, sodass am Ende (fast) gar kein CodeBehind (also Code in der FormKlasse) mehr existiert. Wenn Du Dich für tDS entscheidest - es wird in den höheren .NET-Versionen als obsolet angesehen. Und wieviel CodeBehind Du brauchst, musst Du selber sehen.

    Amelie schrieb:

    Was mir schwerfällt, die Zuordung "Geschäftslogik und BuisenesLogik"
    öhm … deutsch mit etwas griechisch und denglisch mit etwas griechisch. Aber beides ein und dasselbe.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Hattest Du meine Threads (MVVM mit WinForms - kleiner Einstieg für Anfänger, WinForms Projektentwicklung bzgl. der Rolle des Formulars) dazu gelesen und verstanden/nachvollziehen können? Denn sicherlich wäre der Umbau Deines Programms möglich. Aber erstens würde es dann nur mit .NET 7 laufen und zweitens würdest Du es ggf. nicht wiedererkennen, da MVVM eben einen (komplett) anderen Aufbau und Abläufe mit sich bringt.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Amelie schrieb:

    ...lesen von vielen Beträgen...

    ... Artikel zum Lesen immer GUT...
    @'Amelie': Ähm - bei dir habich das Gefühl, es ist nicht immer GUT, weil du dich heillos verzettelst. Quasi dich in alle Richtungen gleichzeitig fortentwickeln willst, und am Ende nur Verwirrung zustande bringst.

    Gut finde ich, dass du scheinbar trotzdem ein Gespür dafür entwickelst, wenn die ach so dolle neue Dinge sich dann am Ende als nur noch umständlicher und komplizierter erweisen als wenn man den Kram bleiben lässt.

    Aber seis drum.
    Wenn du dich noch mit meinem Anwendungs-Umbau-Beispiel und seiner Architektur beschäftigen möchtest, mach einen neuen Thread auf.

    In diesem hier mag es dann im weiteren um MVVM mit WinForms - kleiner Einstieg für Anfänger gehen.
    Weil mein Ansatz ist zwar effektiv, nachvollziehbar, leistungsfähig, und so einfach wie möglich, aber er kann sich nicht mit so einem schönen Namen schmücken.
    Vielleicht sollte ich mir einen ausdenken - wie wäre es mit "Dataset driven Development" (DDD)?



    In diesem Thread noch zu deinen Fragen zu DDD:

    Amelie schrieb:

    Was meinst du mit Daten von den Stationen selbst??
    Naja, deine "Stationen" waren ja nur eine Nummer in der Spalte Messwerte.Station, Und du hattest eine Methode geschrieben, wo diesen Nummern codeseitig Namen zugeordnet wurden, nämlich: "Wohnraum Schlafraum Kochraum Unbekannt".
    Das ist ein Datenmodell-Fehler, weil Stationen und ihre Namen sind Daten, und sollten aus den Daten-Dateien ausgelesen werden, statt per Code festgelegt.

    Im typDataset kannst du nachschauen, dass nun Station Bestandteil des Datenmodells ist.
    Speicher mal mit meiner Anwendung ab - dann sind die Station-Daten auch in der Daten-Datei (schau bitte nach).

    Amelie schrieb:


    Was mir schwerfällt, die Zuordung "Geschäftslogik und BuisenesLogik".
    Wurde schon gesagt: das ist dasselbe.
    Bei DDD gehts um GUI (Forms, UserControls), Datenmodell (typDataset), BusinesLogik (BL), Helpers.
    Das sind die 4 Bereiche, denen etwas zuzuordnen ist. (und "Sonstiges", weil das gibts ja immer)
    BusinesLogik wird als Partial Classes der typisierten Table- und Row-Klassen ausgeführt.
    Deshalb sind die BL-Files meines Code-Beispiels auch zusammen mit dem Dataset im "Data"-Ordner.
    Die BL-Files führen im Namen den Dataset-Namen zuzüglich einer Zuständigkeits-Bezeichnung.
    Die erste BL-Datei kriegt als Anhängsel einfach "BL", und da kommt zunächstmal alle BusinesLogik rein.
    Wenn sie dann zu gross wird, lagere ich Sachen aus: so ist die Datei "DsClima.PrintMesswerte" entstanden.

    Hingegen was du "Calculations" genannt hast, habe ich bislang in "DsClima.BL" belassen - ist ja noch nicht so viel.
    Aber wenn da noch mehr von der Sorte kommt, wirds natürlich auch ausgelagert.



    Wie gesagt: weitere Fragen im anderen Thread - dieser heisst numal "Winform - MVVM" - DDD ist aber was anderes: eine Alternative.
    Meiner Meinung nach wird MVVM nachwievor von WinForms zuwenig unterstützt.
    Aber es gibt durchaus Ähnlichkeiten zwischen DDD und MVVM:
    • Model-Klassen
    • zentrale Mainmodel-Instanz
    • Verknüpfung von GUI und Model via Databinding

    Dieser Beitrag wurde bereits 12 mal editiert, zuletzt von „ErfinderDesRades“ ()

    @VaporiZed

    ​Hattest Du meine Threads...
    In der Tat habe ich das schon überflogen und werde das weiter studieren. Erst dadurch das ich den Artikel hier bei einer "Suche nach etwas ganz anderem" gefunden hatte bin ich auf das "MVVM" gekommen.
    Warum?
    In der Tat war es mir schon immer seltsam, das trotz des OOPs usw noch soviel Code in der FormClass war. Habe mir das, dank deiner vielen Tips immer wieder vor Augen geholt. Ja auch wenn mir das ganze OOP usw oft unlogisch viel an Code vorkommt. :)
    Was ja nun mit dem MVVM noch mehr wird. ?(

    @ErfinderDesRades

    ​bei dir hab ich das Gefühl, es ist nicht immer GUT
    Auf der einen Seite hast du Recht. Auf der anderen Seite ist das ein Teil "meines Asperger Autismus". Ich kann viel Wissen abspeichern, aber es ist sehr schwer, das alles richtig zu sortieren und einzuordnen. Das benötigt alles seine Zeit. Länger als bei Euch "normal neuros" :)

    Das ist auch so ein Umstand, warum ich dann oft hergehe, den ganzen bisherigen Code verwerfe und komplett neu beginne. Ich sicher den alten Code zwar auf einer Festplatte, beginne aber komplett bei NULL.
    Habe da glaube ich schon 10 "alte Versionen" :D


    Dann noch für Euch beiden usw...

    Dann kommen mir oft beim Codschreiben Ideen oder mir fällt etwas auf, was ich nicht im Vorfeld bedachte. Das bring mich dann auch oft raus.

    Ein Beispiel:
    Ich habe in den Setting mit eingebaut ob die Sensoren "kalibiert" wurden. Toll dachte ich und dann beim testen des Codes nur für die Einstellungen fiel mir auf:

    Was mache ich denn, wenn die Sensoren von einander abweichen???? ?(
    DataTable ändern, haufen Code ändern usw... gggrrrrrr

    Dann denke ich wieder, was hier sooft gepredigt wird: Code wartbar schreiben. Code einfach erweiterbar schreiben. Code ....
    Das muss doch alles einfacher sein, schießt mir dann durch den Kopf.
    Aber vielleicht fehlt mir da, wiesooft einfach die Erfahrung beim Codeschreiben.
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Anbei mal ein Anfang (!) eines WinForms-MVVM-Projektes. Ich habe Deine Oberfläche aus Post#4 hergenommen. Die ist unverändert.
    Folgende Änderungen:
    • der Unterbau ist jetzt .NET 7
    • Das Application-Framework wurde deaktiviert und eine Sub Main (im Module Main in der Datei Main.VB) als Startobjekt eingestellt. In dieser Startmethode wird die MainForm-Instanz FrmMain erstellt, die MainViewModel-Instanz VmMain erstellt, für die BindingSource BsViewModel von FrmMain wird als DataSource das VmMain gesetzt.
    • funktionaler Code (also Deine BusinessLogic) wurde erstmal komplett entfernt, da diese (erstmal) nicht für das Verständnis des Unterschieds ClassWinForms <-> MVVM-WinForms relevant ist.
    Code des MainViewModels

    VB.NET-Quellcode

    1. Public Class VmMain
    2. Private _NameOfStation1 As String
    3. Property NameOfStation1 As String
    4. Get
    5. Return _NameOfStation1
    6. End Get
    7. Set
    8. _NameOfStation1 = Value
    9. Stop
    10. End Set
    11. End Property
    12. Private _NameOfStation2 As String
    13. Property NameOfStation2 As String
    14. Get
    15. Return _NameOfStation2
    16. End Get
    17. Set
    18. _NameOfStation2 = Value
    19. Stop
    20. End Set
    21. End Property
    22. Property AlertForStation1IsActive As Boolean
    23. Property AlertForStation2IsActive As Boolean
    24. Property SaveDataRelayCommand As New RelayCommand(AddressOf SaveData)
    25. Private Sub SaveData()
    26. Stop
    27. End Sub
    28. End Class

    Mit normalem .NET-Framework-DataBinding sind fast alle Sachen aus dem hiesigen Projekt eh schon möglich: die erste Stationsnamentextbox ist über BsViewModel an die VmMain-Property NameOfStation1 gebunden. Wird der Name auf dem Form geändert und validiert (z.B. durch Verlassen der TextBox), wird der Property-Setter in der VmMain-Klasse aufgerufen und die Ausführung des Codes wird in Zeile#10 durch das Stop gestoppt, damit Du siehst, wann was passiert. Für den Namen der 2. Station habe ich im Designer eingestellt, dass der PropertySetter (also ab Zeile#19) sofort aufgerufen wird (also ohne die Validierung abzuwarten), wenn der Name im GUI geändert wird.

    btw: die ausführliche Schreibweise der Propertys zzgl. der Variablen wie _NameOfStation1 habe ich nur eingebaut, damit wir die Setter und das darin enthaltene Stop nutzen können, damit Du siehst, wann was passiert. Später reicht statt z.B. den Zeilen#3-12 meistens die einfache AutoProperty-Schreibweise: Property NameOfStation1 As String.

    Was jetzt ab .NET 7 neu ist und bei diesem Programm geht, ist die Tatsache, dass auch Button-Clicks zu einer Aktion in VmMain führen, ohne dies im CodeBehind von FrmMain explizit durch einen EventHandler angeben zu müssen. Dazu brauchst Du die RelayCommand-Klasse, die im Projekt enthalten ist. Akzeptiere erstmal die Existenz der Klasse, ohne sie verstehen zu müssen. Was Du wissen musst: Diese allgemeine Klasse erlaubt Dir, eine VmMain-Property zu erstellen, an die ein Button im GUI per DataBinding gebunden werden kann und die mit einer VmMain-Methode verbunden wird. Der GUI-Button Speichern ist mit der VmMain-Property namens SaveDataRelayCommand per DataBinding verknüpft, was dazu führt, dass die in VmMain hinterlegte Aktion SaveData ausgeführt wird, sobald der Button geklickt wird. Und als Konsequenz kannst Du Dir mal den Code in FrmMain.vb ansehen. Die Klasse ist (bis auf den Designer-Code) leer! Dein BusinessLogic-Code kann also komplett in VmMain oder ggf. anderen Klassen sein. Das GUI wird nur noch über die BS an die Details von VmMain gebunden und sonst gar nix. Das ist m.E. das Schöne an MVVM.

    Über das Model haben wir noch nicht gesprochen, aber das ist für den Aufbau der hiesigen Anwendung auch (noch) nicht relevant.
    Dateien
    • MVVM Übung.zip

      (86,5 kB, 26 mal heruntergeladen, zuletzt: )
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.