MVVM Umsetzung mit WinForms

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

Es gibt 194 Antworten in diesem Thema. Der letzte Beitrag () ist von Amelie.

    Haudruferzappeltnoch schrieb:

    wieso ist das ein Notfall?
    Weil es der Standardweg ist, eine tDS-Instanz auf dem Form zu erstellen und in dem Components zu haben (soweit gleich mit dem BS-VM-Paket) und dann eben auch direkt daran zu binden. Wenn man jetzt da das tDS rausnimmt, um bei der App diesbezüglich eine View-VM-Trennung zu machen, wird das auch eine Umstellung für den ein oder anderen "DDD"-Entwickler. Naja, oder vielleicht auch nicht. Man könnte ja ne BS für das tDS erstellen, so wie ich es früher gemacht habe. Damit konnte ich die formübergreifende tDS-Instanz-Übergabe besser bewerkstelligen.
    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.

    Haudruferzappeltnoch schrieb:

    Die Instanz auf dem Form zu haben ist ja auch nicht schlimm.
    hmm - ich fand das schon immer ein verheerendes WinForms-FehlDesign, dass jedes Form sein eigenes Dataset enthält (im DesignerCode instanziert).
    Aber ich hab halt einen Workaround gefunden - eine Methode, die alle Bindings umstöpselt von der lokalen tDS-Instanz auf die globale.

    Haudruferzappeltnoch schrieb:

    das ist in WPF der DataContext, da nimmt man sich auch die Instance der VM rein.
    Ein Wpf-Window instanziert kein Viewmodel, sondern bindet nur seinen DataContext ans globale Viewmodel. Da ist also von vornherein richtig gelöst, was in WinForms mein Workaround erst graderücken muss.
    Moin moin

    Du kannst das Zellenformat vorab im Designer festlegen:

    Ja das weis ich und das hatte ich auch erst so gemacht. Aus irgendeinem Grund wurde das Datum und eine andere Spalte aber immer "falsch" formatiert.
    Z.B. bei der Luftfeuchte wurde immer 55.00 % angezeigt, beim Datum: 2024-07-14T17:36:15.4780243+02:00

    ​Das ist GUI-Arbeit, also in View,


    OK, dann habe ich ja doch wieder Code auf dem Form. Sehr verwirrend :!:

    ihr VM auf GUI-Unabhängigkeit zu prüfen


    Nunja das meiste funktioniert auch ohne eine GUI. Das sehe ich ja an den ganzen "Debug/Console-Ausgaben" die ich immer wieder in die Klassen / Methoden einbaue.
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    ErfinderDesRades schrieb:

    dass jedes Form sein eigenes Dataset enthält (im DesignerCode instanziert)
    Das lässt sich beheben indem man den Designer anfasst. Du nutzt ja die Shared Instanz, die kann man als DataSource auch im Designer bei der BindingSource angeben, allerdings lädt der Designer dann nicht mehr. Die Anwendung kompiliert und läuft aber weiterhin.
    Oder man könnte ein dummyDS aufs Form tun und so die DGVs einstellen und dann beim Aufruf des Forms die DataSource umstöpseln. Das ist wahrscheinlich was du machst.

    Der Designer meldet wenn man dort die globale Instanz verwenden will, dass der Member nicht existiert.
    Das ist der einzige Unterschied zum DataContext
    Aber das ist ja nicht die Schuld des DataSets, von daher ist an dieser Stelle WinForms altbackener als tDS

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

    offtopic
    Dann werf ich nochmals zu dem Thema ein, was ich ebenfalls schon ein paar Mal in den vergangenen Jahren dazu schrieb und hier auch kurz erwähnt hatte: Jedes Form hat seine tDS-Instanz FtDS, man packt ne BS BsTds auf's Form, die an FtDS bindet, alle anderes BSs binden an die BsTds statt an FtDS und wenn man dann ein Form F2 von einem anderen Form F1 aus aufruft, legt man die tatsächliche tDS-Instanz als DataSource der F2-BsTds fest, z.B. mit F2.BsTds.DataSource = F1.BsTds.DataSource. Alle BSs von F2 sind dann effektiv immer an das one-and-only tDS angebunden und alles ist gut.
    /offtopic

    Aber zurück zum Thema: @Amelie: Ich hätte mir denken müssen, dass Dich meine Aussage verwirrt, weil ich anfangs immer schrieb: kein Code im View. Ich hätte damals schon klar sagen müssen: kein Code im View, der nicht ausschließlich für die Optik zuständig ist. MVVM ist eine Schichten- und Aufgabentrennung. Code im View darf sich nur um Viewaufgaben kümmern. Und das ist eben Optik. Man könnte auch sagen: Um das View kümmert sich ein menschlicher Designer. Er kann den Code im View-CodeBehind so erstellen, dass das View hübsch aussieht. Für die Businesslogik ist jemand in einer anderen Abteilung zuständig. Der menschliche Designer soll sich nur darum kümmern, wie die Oberfläche/das View aussieht. Dazu darf er (und muss es manchmal auch) Code verwenden. Aber eben nur solchen, der die Daten zwar auswerten darf, aber diese nicht manipuliert. Also quasi ReadOnly.

    Ich hoffe, dass mir die anderen da zustimmen, ansonsten bitte präzisieren oder korrigieren.

    Amelie schrieb:

    Aus irgendeinem Grund wurde das Datum und eine andere Spalte aber immer "falsch" formatiert.
    Dann ist das eine Sache, die wir korrigieren können. Nur müssen wir das erstmal von Dir erfahren, dass es da ein Problem gibt. Jetzt weißt Du, dass es geht. Bei Datum kannst Du g festlegen, um Datum und Zeit in Kurzformat zu bekommen. Bei der Luftfeuchtigkeit kannst Du bei datentyp- und wertabhängig mal probieren. Vielleicht %, vielleicht # "%"
    Bilder
    • Formatfestlegung.png

      45,79 kB, 1.012×655, 27 mal angesehen
    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.

    VaporiZed schrieb:

    Ich hoffe, dass mir die anderen da zustimmen, ansonsten bitte präzisieren oder korrigieren.
    Ja, ich denke, du beschreibst die MVVM-Forderungen ganz richtig.
    Nur würde ich das laxer handhaben.
    Weil Ich halte Winforms generell (noch?) für ungeeignet, um damit ein strenges MVVM umzusetzen.
    Da hilft auch kein CommandBinding, erst recht nicht, wenn so dermassen buggy.
    Mir scheint WinForms-MVVM nur mit unverhältnismässigem Zusatz-Aufwand möglich, und ohne wirklichen architektonischen Gewinn. ZB die berühmte GUI-Austauschbarkeit - Das ist doch eine theoretische Phantasterei, die wir Normalsterbliche niemals praktisch umsetzen werden.

    Beispielsweise so eine simple Anforderung an ein DGV, einen doppelgeklicksten Datensatz im Einzel-Formular editieren zu können.
    In Oldschool ist das banal: 5 Zeilen ins Codebehind, die jeder Anfänger versteht.
    In MVVM wäre das doch ein gewaltiger Aufriss, mit Factories ("Service" ist glaub der falsche Begriff dafür), Interfaces und Kram, oder irre ich mich?
    Und jeder machts auch noch anders, und jede Variante ist auf ihre Weise undurchsichtig - für was?

    Oder du selektierst 6 Datensätze, um sie mit einem Click zu löschen - das ist auch so ein Fall wo Oldschool sich langweilt, während MVVM einen Breakdance mit Kopfstand aufführt?

    Also ich bin sehr dafür, komplexere Datenverarbeitung möglichst aus dem CodeBehind herauszuverlagern ins Model, oder Viewmodel.
    Aber die Control-Eventhandler täte ich im CodeBehind belassen.
    Ist halt Winforms, und nicht Wpf.
    @VaporiZednullHabe nun mal ein bissel weiter gemacht und ja klappt soweit. (siehe Bild)
    Ich hatte das Private Sub UpdateShow() zwar auch schon im ViewModel aber da hatte ich das Problem, das ich immer erst einmal mit dem Monat blättern musste, damit die Daten angezeigt wurden.
    Hab das bis jetzt auch nicht anders hinbekommen... wohl grade blind...

    PS: das mit dem % muss so sein im Designer:'%'

    Das Model:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. '/ file: DailyDataLoader.vb ( Model )
    2. Public Class DailyDataLoader
    3. Public Property CurrFilename As String
    4. Get
    5. Return $"DailyDatas_{Configuration.Instance.CurDatum.ToString("MM_yyyy")}.xml"
    6. End Get
    7. Set(value As String)
    8. End Set
    9. End Property
    10. ' Pfad zur XML-Datei mit den täglichen Wetterdaten
    11. Private ReadOnly DailyXmlPath As String = Path.Combine(Configuration.Instance.DataXmlFilePath, CurrFilename)
    12. ' Methode zum Laden aller täglichen Wetterdaten aus der XML-Datei
    13. Public Function LoadAllDailyWeatherData() As List(Of DailyWeatherData)
    14. Dim dailyWeatherDataList As New List(Of DailyWeatherData)()
    15. If File.Exists(DailyXmlPath) Then
    16. Dim ds As New DataSet()
    17. ds.ReadXml(DailyXmlPath)
    18. If ds.Tables.Contains("DailyMeasurements") AndAlso ds.Tables("DailyMeasurements").Rows.Count > 0 Then
    19. For Each row As DataRow In ds.Tables("DailyMeasurements").Rows
    20. Dim dailyWeatherData As New DailyWeatherData()
    21. dailyWeatherData.ID = If(IsDBNull(row("ID")), 0, Convert.ToInt32(row("ID")))
    22. dailyWeatherData.Datum = If(IsDBNull(row("Datum")), DateTime.MinValue, Convert.ToDateTime(row("Datum")))
    23. dailyWeatherData.Temp1 = If(IsDBNull(row("Temp1")), 0D, Convert.ToDecimal(row("Temp1")))
    24. dailyWeatherData.Temp2 = If(IsDBNull(row("Temp2")), 0D, Convert.ToDecimal(row("Temp2")))
    25. dailyWeatherData.Temp3 = If(IsDBNull(row("Temp3")), 0D, Convert.ToDecimal(row("Temp3")))
    26. dailyWeatherData.Humidi1 = If(IsDBNull(row("Humidi1")), 0D, Convert.ToDecimal(row("Humidi1")))
    27. dailyWeatherData.Humidi2 = If(IsDBNull(row("Humidi2")), 0D, Convert.ToDecimal(row("Humidi2")))
    28. dailyWeatherData.Humidi3 = If(IsDBNull(row("Humidi3")), 0D, Convert.ToDecimal(row("Humidi3")))
    29. dailyWeatherData.Pressure1 = If(IsDBNull(row("Pressure1")), 0D, Convert.ToDecimal(row("Pressure1")))
    30. dailyWeatherData.Pressure2 = If(IsDBNull(row("Pressure2")), 0D, Convert.ToDecimal(row("Pressure2")))
    31. dailyWeatherData.Pressure3 = If(IsDBNull(row("Pressure3")), 0D, Convert.ToDecimal(row("Pressure3")))
    32. ' Das DailyWeatherData-Objekt zur Liste hinzufügen
    33. dailyWeatherDataList.Add(dailyWeatherData)
    34. Next
    35. End If
    36. End If
    37. Return dailyWeatherDataList
    38. End Function
    39. End Class



    Das ViewModel:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. '/ file: P0_ShowDataViewModel.vb ( ViewModel )
    2. Partial Public Class ShowDataViewModel
    3. Inherits PropertyChange
    4. ' Singleton-Instanz des ViewModels
    5. Private Shared ReadOnly _instance As New Lazy(Of ShowDataViewModel)(Function() New ShowDataViewModel())
    6. Public Shared ReadOnly Property Instance As ShowDataViewModel
    7. Get
    8. Return _instance.Value
    9. End Get
    10. End Property
    11. ' BindingList zur Datenbindung mit dem DataGridView
    12. Public ReadOnly Property MonthlyWeatherDataList As New BindingList(Of WeatherData)
    13. Public ReadOnly Property DailyWeatherDataList As New BindingList(Of DailyWeatherData)
    14. Public Sub New()
    15. AktlMonth = Configuration.Instance.CurDatum
    16. End Sub
    17. ' Methoden zum Laden der Daten aus dem Model ins ViewModel
    18. Public Sub LoadMonthlyDataFromModel(MonthlyMeasurementsList As List(Of WeatherData))
    19. MonthlyWeatherDataList.Clear()
    20. For Each MonthlyMeasurement In MonthlyMeasurementsList
    21. MonthlyWeatherDataList.Add(MonthlyMeasurement)
    22. Next
    23. End Sub
    24. Public Sub LoadDailyDataFromModel(dailyMeasurementsList As List(Of DailyWeatherData))
    25. DailyWeatherDataList.Clear()
    26. For Each dailyMeasurement In dailyMeasurementsList
    27. DailyWeatherDataList.Add(dailyMeasurement)
    28. Next
    29. End Sub
    30. ' Methode für den vorherigen Monat
    31. Public Property MoveToPreviousMonthRelayCommand As New RelayCommand(AddressOf PreviousMonth)
    32. Private Sub PreviousMonth()
    33. Configuration.Instance.MoveToPreviousMonth()
    34. AktlMonth = Configuration.Instance.CurDatum
    35. End Sub
    36. ' Methode für den nächsten Monat
    37. Public Property MoveToNextMonthRelayCommand As New RelayCommand(AddressOf NextMonth)
    38. Private Sub NextMonth()
    39. Configuration.Instance.MoveToNextMonth()
    40. AktlMonth = Configuration.Instance.CurDatum
    41. End Sub
    42. ' Methode um den ausgewählten Monat anzuzeigen
    43. Private _aktlMonth As DateTime
    44. Public Property AktlMonth As DateTime
    45. Get
    46. Return _aktlMonth
    47. End Get
    48. Set(value As DateTime)
    49. If _aktlMonth <> value Then
    50. _aktlMonth = value
    51. OnPropertyChanged()
    52. End If
    53. End Set
    54. End Property
    55. End Class



    Das View:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. '/ file: FrmSowCityDatas.vb
    2. Public Class FrmShowCityDatas
    3. Private ReadOnly _viewModel As ShowDataViewModel = ShowDataViewModel.Instance
    4. Public Sub New()
    5. InitializeComponent()
    6. DgvDailydatas.AutoGenerateColumns = False
    7. DgvMonthdatas.AutoGenerateColumns = False
    8. UpdateShow()
    9. End Sub
    10. Private Sub UpdateShow()
    11. LoadAndSetData()
    12. ShowDataInDGV()
    13. UpdateMonth()
    14. End Sub
    15. Private Sub LoadAndSetData()
    16. Dim monthlyDataLoader As New MonthlyDataLoader()
    17. Dim monthlyWeatherDataList As List(Of WeatherData) = monthlyDataLoader.LoadAllMonthlyWeatherData()
    18. _viewModel.LoadMonthlyDataFromModel(monthlyWeatherDataList)
    19. Dim dailyDataLoader As New DailyDataLoader()
    20. Dim dailyWeatherDataList As List(Of DailyWeatherData) = dailyDataLoader.LoadAllDailyWeatherData()
    21. _viewModel.LoadDailyDataFromModel(dailyWeatherDataList)
    22. End Sub
    23. Private Sub ShowDataInDGV()
    24. DgvDailydatas.DataSource = _viewModel.DailyWeatherDataList
    25. DgvMonthdatas.DataSource = _viewModel.MonthlyWeatherDataList
    26. End Sub
    27. Private Sub UpdateMonth()
    28. MonthTxtBoxMenuItem.Text = _viewModel.AktlMonth.ToString("MMMM yyyy")
    29. End Sub
    30. Private Sub MonthPrevMenuItem_Click(sender As Object, e As EventArgs) Handles MonthPrevMenuItem.Click
    31. _viewModel.MoveToPreviousMonthRelayCommand.Execute(Nothing)
    32. UpdateShow()
    33. End Sub
    34. Private Sub MonthNextMenuItem_Click(sender As Object, e As EventArgs) Handles MonthNextMenuItem.Click
    35. _viewModel.MoveToNextMonthRelayCommand.Execute(Nothing)
    36. UpdateShow()
    37. End Sub
    38. End Class

    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

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

    Würdest Du das Projekt hochladen wollen? Dann kann ich auch einen Blick auf die DataBindings werfen und besser damit rumspielen und nach Verbesserungen schauen.
    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.
    @VaporiZed

    Es ist echt zum <X mit dem S.....

    Haste das eine endlich zum laufen gebracht, funktionieren andere Sachen nicht mehr. :cursing:

    Nun klappt es mit den Monats-Dateien erstellen und im DGV anzuzeigen. Das Blättern der Monate funktioniert und dann..

    Gebe Daten ins DGV ein; Speichern. Datei wird geändert (Zeitstempel im Explorer) aber es werden keine Daten die ich eingegeben habe gespeichert.
    Obwohl ich mir Mühe gebe, kommt es mir vor als wenn ich zwischen Haufen von Dateien hinundher springe und dann auf dem Weg alles an Daten etc verliere....
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

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

    1. In StartMain gibt es die Zeile

      VB.NET-Quellcode

      1. Dim mainViewModel As New MainViewModel(Function() windowService, configViewModel, dataService)
      und damit im mainViewModel-Konstruktor:

      VB.NET-Quellcode

      1. Public Sub New(windowServiceFactory As Func(Of IWindowService), configViewModel As ConfigViewModel, dataService As DataService)
      Warum verwendest Du dieses Func-Konstrukt?
    2. Wozu gibt es eine BindingSource im DataService? Die BindingSource ist eine WinForms-Komponente und gehört somit ins View/GUI/Form.
    3. Der Konstruktor in der WinFormsWindowService-Klasse:

      VB.NET-Quellcode

      1. Public Sub New(mainViewModel As MainViewModel, configViewModel As ConfigViewModel)
      Aber der mainViewModel-Parameter wird nicht verwendet. Wozu also?
    4. Warum wird in Public Sub ShowMain() das ConfigViewModel mitgegeben?
    5. Warum kennt die WinFormsWindowService-Klasse überhaupt konkrete ViewModels?
    6. Diese Lazy(Of …)(Function() New …)-Konstrukte find ich zwar interessant. Aber wozu brauchst Du sie?
    Zu 5.: Ich habe mal die konkreten Datentypen (bis auf die Forms) entfernt. Dadurch ersparst Du Dir die Übergabe und Aktualisierung der ViewModels in dem WindowService. Dem WindowService kann's ja wurscht sein, von welchem Typ das ViewModel ist, soll sich doch das Form darum kümmern: Wenn der WindowService aufgerufen wird, gibt man die gewünschte ViewModel-Instanz an den WindowService, welcher aber diese Instanz als Object entgegennimmt und an das gewünschte Form weiterreicht. Das Form castet das Teil dann wieder zurück in den Solltyp. Das nennt man Boxing/Unboxing. Was soll jetzt der Blödsinn, also erst in ein anonymes Paket einpacken und später wieder auspacken? Der WindowService muss nicht mehr wissen, was für ViewModels es gibt. Du wärst damit nur noch wenig davon entfernt, den WindowService so zu gestalten, dass er in anderen MVVM-Projekten auch verwendet werden kann. Dazu müssten wir nur noch die Form-Typen aus der WindowService-Klasse entfernen. Aber eines nach dem anderen.

    Dass das DataSet und die BindingSource im DataService nun direkt als Datenquelle hergenommen werden, ist net so dolle. Du kannst gern ein typisiertes DataSet verwenden. Aber untypisiert macht es die Sache fehleranfäiig. Grundsätzlich würde ich sogar Modelklassen verwenden, also sog. POCOs. Die übernehmen dann die Daten aus der Datenquelle und deren Daten werden beim Speichern auch wieder in die Datenquelle reingeschoben. Was diese Datenquelle ist und wie die Daten von A nach B kommen, bleibt Dir überlassen. Du kannst ne XML-Datei mit angeschlossenem tDS verwenden, Du kannst die Daten auch direkt als JSON abspeichern oder irgendwann ne Datenbank anschließen. Aber die direkte Verwendung eines untypisierten DataSets plus BindingSource in einer Datenklasse ist nicht empfehlenswert.
    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.
    @VaporiZed

    Ich habe seit gestern noch wieter gemacht.. mit dem Resultat, das alles nicht mehr funktioniert.

    Es ist enfach zu frustrierend wenn irgendwann nichts mehr geht. Bin dann wohl zu blöd zum progrmaiern.. :cursing:

    Danke trotzdem. <3
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    mit dem Resultat, das alles nicht mehr funktioniert.
    Aber schrittweise Backups machst Du schon, oder? Das musste ich über die Jahre schmerzhaft lernen: Wenn ein Fehler behoben oder ein neues Feature implementiert wurde, umgehend ein Backup des Ist-Zustands machen. Und dabei die Programmversionsnummer aktualisieren und die Änderung in Stichpunkten zusammenfassen.
    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.
    @VaporiZed

    Moin moin

    1.) Dieses Lazy gedööööns ;)
    Als ich noch kein VS 2022 hatte machte ich die Singelton Classes immer so:

    VB.NET-Quellcode

    1. Private Shared ReadOnly _instance As New MainViewModel()
    2. Public Shared ReadOnly Property Instance As MainViewModel
    3. Get
    4. Return _instance
    5. End Get
    6. End Property


    Das hat VS 2022 immer angemeckert. Dann suche ich im www und fragte bei GPT nach Infos dazu.
    ​Thread-Sicherheit: Lazy(Of T) bietet eine eingebaute Thread-Sicherheit, die sicherstellt, dass nur eine Instanz des Objekts erstellt wird, selbst wenn mehrere Threads gleichzeitig auf die Instance-Eigenschaft zugreifen.


    Das ist wohl der Hauptvorteil.

    -------------
    ​Aber schrittweise Backups...

    Ja habe ich gemacht und gestern Mittag alles auf die externe Platte kopiert und Intern gelöscht!
    Da ist soviel durcheinander usw... ich blicke schon nicht mehr durch. :cursing:

    Habe nun alles bereinigt ( aus das Studio ) und neu begonnen.... Dazu später mehr ...
    .....

    Ich habe ja eine "fertige, laufende" Version, die das macht was ich mir vorstellte. Ist halt Spaghetti - Code vom aller feinstem. <X <X Alles wild durcheinander usw...
    Jetzt hat aber ein Bekannter das gesehen und möchte das auch haben... mit ein paar Abwandlungen...

    Also habe ich ein ganz sauberes Projekt angelegt und schon mal etwas Vorbereitet. Will aber Schritt für Schritt vorgehen.
    ​Modelklassen verwenden, also sog. POCOs


    Habe ich erstellt usw.. ... Später mehr inkl sauberen Code.
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    Also habe ich ein ganz sauberes Projekt angelegt und schon mal etwas Vorbereitet.
    Das heisst, nach 175 Posts kann dieser Thread jetzt auch wieder von vorne anfangen?
    hmm...
    Vielleicht solltet ihr Regeln einführen weil dieses "Ichmachmalwas..." -> "hab Schonmal weitergemacht..." -> "hab wieder von vorne angefangen..." - ich fürchte, auf Dauer werden dich nicht viele dabei begleiten wollen.
    Also ich verfolge diesen Thread ja schon. Denn ich schrecke davor zurück, MVVM mit WinForms zu kombinieren. Da lohnt sich schon ein Einblick, welche Erfahrungen da gemacht werden. Des weiteren bin ich der Meinung, dass redesigns eher zu selten als zu oft gemacht werden. Mir stellt sich jedoch eine grundsätzlicherer Frage : ist die Verwendung von WinForms als Viewmodell als Strategie zu teuer?
    Zusätzlich würde ich noch anmerken wollen, das ich MVVM mit den bisher genannten Argumenten nicht verkaufen könnte.
    Man möge mich korrigieren, aber ich glaube nur die Argumente
    >Designabteilung arbeitet freier und
    >Codeparadigmen sind besser
    gelesen zu haben.
    Mein Argument pro MVVM wäre die Vermutung, dass es einfacher automatisierbar ist. Das wäre in meiner Situation auch sehr schlagkräftig.

    Ich stelle mir folgende zusätzliche Fragen zu MVVM (die ggfls je nach Umfang des zu erstellenden Programms variieren können)
    a) ist der Code dadurch übersichlicher / einfacher
    b) ist die Wartbarkeit besser ?
    ​c) ist die Implementierung der Funktionalitäten damit weniger fehleranfällig ?
    d) ist die Erweiterbarkeit des Codes dadurch besser ?
    e) geht das Implementieren schneller?
    f) wie hoch sind die Lernhürden (Dichte und Anzahl der Fachbegriffe, die die Erlärungen spicken) ?
    g) wie sieht es mit der multiplattformunterstützung aus ?
    h) gibt es Einschränkungen, die die Implementierung unmöglich machen bzw ad absurdum führt ? (spezielle Controls,..)

    Selbst wenn die Antworten individuell recht unterschiedlich ausfallen können und eine Auswertung des weltweit vorhandenen Programmcodes wünschenswert aber unmöglich ist, bleiben diese Fragen im meinen Augen Key. Unter der Annahme dass es darum geht, das Programm in einen möglicht funktionalen Zustand zeitnah fertig zu stellen. Wenn überhaupt, dann fehlen eher noch einige Fragen.
    Ich frage also nach einem Resumee der Beteiligten unter Berücksichtigung einiger der Fragen, und was nun tatsächlich best practice ist und was nicht.
    Moin moin

    Ich selber bezeichne mich ja noch immer als "Programmier-Anfänger" und durch mein Asperger habe ich es nicht immer so einfach wie andere.

    Meine Programme sind zu 90% reine Übungen und rein private. Auch wenn nun ein Bekannter mein kleines Prog haben möchte, freut mich das zwar aber ich sehe das dann nochmal als ansporn es besser zu machen als meine eigene "Spaghetti-Code-Version" :)

    Um Praxis zu bekommen und wenn ich mich mal wieder total verheddere, muss ich einfach neu, bei Null beginnen, sonst kommt ich aus dem verkorstem Code nicht mehr raus.

    @ErfinderDesRades
    Nein es muss nicht von vorne begonnen werden. Der Grundaufbau bleibt ja erhalten.
    Das einzige was ich wegen der Probleme mit dem ".Net 8" gemacht habe, ich bin zurück zum ".Net FW"

    @Coldfire
    Aus meiner Sicht und Erfahrung, mein bestehendes kleines Prog nach "MvvM" zu redisignen, versuche ich hier ein paar deiner Fragen zu beantworten.

    a) für mich ist es sehr anstengend die Übersicht zu behalten. Ich erwähnte ja schon, das es mit oft so vorkommt, das ich von "a" nach "b" nach "c" und wieder zurück nach "a" springe.
    Ja oft muss man das wohl im "MvvM" wobei eigentlich ist es ja: "M-VM-V" ;)

    b) kann ich noch nicht sagen
    c) & d) wäre durchaus möglich
    e) wenn man das ganze mal zu 100% verstanden hat und ein 100% Wasserdichtes Konzept und viel Programmiererfahrung hat, geht es bestimmt schneller :)
    f) für mich noch sehr hoch und an reines MvvM mit Wpf ... gehe ich noch lange nicht dran.
    g) weiß ich nicht
    h) bei den Controls habe ich festgestellt, das die "Menue-Leiste" und "Status-Leiste" mit diesen einfachen Bindungen nicht zurecht kommen:

    VB.NET-Quellcode

    1. ​LblEvent.DataBindings.Add(New Binding("Text", _configInstance, NameOf(_configInstance.Eventmessage), True, DataSourceUpdateMode.OnPropertyChanged))

    Dabei ist es egal ob es ein Label, eine Textbox oder eine ComboBox aus der MenueLeiste ist.

    So als Resumeè was ich bis her sagen kann.
    An dem jetzigen Code sehe ich schon, das es "aufgeräumter" ist als noch mit meiner herkömmlichen Classen-Methode. Da war halt zuviel in den einzelnen Classen was da nicht hingehörte. Und ja ist bestimmt jetzt auch noch so, weil es für mich oft noch verwirrend ist;
    kommt der Code-Block nun ins "Model" oder ins "ViewModel" ?(

    ... oder in den Trash :D

    Was ich noch sagen kann, deswegen ja auch der "Neubegin":
    Ich der vorletzen Version habe ich, schön nach dem Tenor von @ErfinderDesRades ,ein tDataset usw im Designer aufgebaut. Dann habe ich versucht dafür ein Interface zu erstellen und dann fingen die großen Probleme an. Habe dann solange rumgemacht, bis nichts mehr ging.... :S

    Also nun den Vorschlag von @VaporiZed mit den "POCOs".

    Erst das "Model" erstellen und dann ... ... War zwar viel Schreibarbeit bis ich das Laden und Speichern hinbekommen hatte aber es klappt.


    Noch zum Abschluss für diesen Text hier.
    Ich finde es äußerst verwirrend, wenn Code der in VS2017 / VS2019 noch funktionierte dann in VS2022 nicht mehr geht... Erwähnt ich hier auch schon, bzgl der Singelton Class ...
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Coldfire schrieb:

    >Codeparadigmen sind besser
    Ein Codeparadigma entsteht, weil auf die Aspekte a-e geschaut wird. Das denkt sich ja nicht irgendwer aus weils Spaß macht, bzw. falls doch, dann wird es eher wenig von anderen übernommen.
    Außerdem folgt c eher aus a als das ein spezielles Paradigma das explizit verbuchen könnte und wie ist d definiert, wenn nicht durch e?

    Zu f):
    Das Pattern MVVM für sich würde ich sagen hat geringe Lernhürden.
    Dazu kommt aber die Einbettung, WPF hatte da deutlich mehr als das Pattern. In WinForms stelle ich es mir einfacher vor. Aber in WinForms sehe ich wie schon geschrieben die Motivation nicht.

    Haudruferzappeltnoch schrieb:

    in Codeparadigma entsteht, weil auf die Aspekte a-e geschaut wird.


    Man sollte jedoch auch prüfen, ob die Versprechen von diesem Codeparadigma auch erfüllt werden. Das Paradigma an sich ist wertlos. Aktuell lese ich ja hereaus, dass es was briningt. Vielleicht bin ich ja zu skeptisch.