Ideen zur Speicherung

  • WPF
  • .NET 5–6

Es gibt 25 Antworten in diesem Thema. Der letzte Beitrag () ist von asusdk.

    Ideen zur Speicherung

    Hi Ihr Lieben,

    ich hab mir ein kleines Tool für die Arbeit geschrieben, anschließend habe ich einen IDataService eingebaut, um die vorhandenen Klassen per Serialisierung zu speichern. Wenn ich das manuell ausführe, funktioniert das auch einwandfrei.
    Im Endeffekt suche ich eine Idee, wie ich aus einer Subklasse heraus, die Speicherfunktion ausführen kann, sobald das Programm beendet wird.

    die erwähnte Subklasse:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Collections.ObjectModel
    2. Public Class TicketsViewModel
    3. Inherits BaseViewModel
    4. Private TicketCounter As Integer = 0
    5. Private _ticketsservice As ITicketsDataService
    6. Public Sub New(service As ITicketsDataService)
    7. 'OpenTickets = New ObservableCollection(Of TicketViewModel)
    8. _ticketsservice = service
    9. OpenTickets = _ticketsservice.GetTickets
    10. loadTickets()
    11. If IsInDesignMode() Then
    12. For I As Integer = 0 To 4
    13. AddTicket()
    14. Next
    15. End If
    16. End Sub
    17. Sub loadTickets()
    18. OpenTickets = _ticketsservice.GetTickets
    19. End Sub
    20. Public Sub savetickets()
    21. _ticketsservice.SaveTickets(OpenTickets)
    22. End Sub
    23. Private _OpenTickets As ObservableCollection(Of TicketViewModel)
    24. Public Property OpenTickets() As ObservableCollection(Of TicketViewModel)
    25. Get
    26. Return _OpenTickets
    27. End Get
    28. Set(ByVal value As ObservableCollection(Of TicketViewModel))
    29. ChangePropIfDifferent(value, _OpenTickets)
    30. End Set
    31. End Property
    32. Private _SelectedTicket As TicketViewModel
    33. Public Property SelectedTicket() As TicketViewModel
    34. Get
    35. Return _SelectedTicket
    36. End Get
    37. Set(ByVal value As TicketViewModel)
    38. ChangePropIfDifferent(value, _SelectedTicket)
    39. End Set
    40. End Property
    41. Sub AddTicket()
    42. OpenTickets.Add(New TicketViewModel(TicketCounter + 1) With {.TicketText = "afgzhubaijfasf"})
    43. TicketCounter += 1
    44. End Sub
    45. Sub RemoveTicket()
    46. If SelectedTicket IsNot Nothing Then
    47. OpenTickets.Remove(SelectedTicket)
    48. End If
    49. End Sub
    50. Public ReadOnly Property AddTicketCommand As New RelayCommand(AddressOf AddTicketCommand_Execute)
    51. Private Sub AddTicketCommand_Execute(obj As Object)
    52. AddTicket()
    53. End Sub
    54. Public ReadOnly Property RemoveTicketCommand As New RelayCommand(AddressOf RemoveTicketCommand_Execute, Function(o) SelectedTicket IsNot Nothing)
    55. Private Sub RemoveTicketCommand_Execute(obj As Object)
    56. If MessageBox.Show($"Do you really want to Delete Ticket number {SelectedTicket.NumericalID} from the List?", "Are you sure?", MessageBoxButton.YesNo, MessageBoxImage.Question) <> MessageBoxResult.No Then
    57. RemoveTicket()
    58. End If
    59. End Sub
    60. End Class


    Nur leider fehlt mir jede Idee, wie ich das realisieren könnte. Vielleicht habt ihr ja eine? =)



    Nachtrag: die einzige Idee, die ich sonst noch hätte, wäre es per Timer zu lösen, aber irgendwie find ich das nicht besonders elegant
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „asusdk“ ()

    asusdk schrieb:

    die Speicherfunktion ausführen kann, sobald das Programm beendet wird

    Wie jetzt?

    Du willst erst speichern wenn das Programm beendet wird?
    Und was wenn es der User über den TaskManager beendet? Was wenn es abstürzt? Und, und, und.....

    Wie wäre es wenn du in dem Moment speicherst wenn sich die Daten ändern?

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Das wäre natürlich am besten, jedoch wüsste ich ebenso nicht wie ich das realisieren sollte, ich meine klar, ich könnte jedes Mal speichern, wenn ein neues Ticket erstellt wird,
    und jedes Mal, wenn ich eins entferne, das hab ich so weit auch getestet und das würde funktionieren, jedoch wüsste ich nicht wie ich erreichen könnte,
    dass auch automatisch gespeichert wird, wenn sich innerhalb eines Tickets etwas ändert, das wird ja per Binding in die View transportiert, in diese Richtung sind auch alle Versuche gescheitert.

    Also in meinem TicketsViewModel gibt es eine ObservableCollection(of TicketViewmodel) soweit so klar, könnte man ja wie erwähnt beim Hinzufügen oder entfernen speichern. Aber wie könnte ich automatisch speichern, wenn sich in einem
    der in der Collection befindlichen Tickets etwas ändert?
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

    Akanel schrieb:

    Vielleicht da wo auch die View benachrichtigt wird das sich etwas geändert hat?

    Naja das passiert ja im Hintergrund per Binding, ich wüsste leider nicht wie ich hier eingreifen könnte
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    Vollzitat des direkten Vorposts an dieser Stelle entfernt ~VaporiZed

    Ich verwende das BaseViewModel von dir, mit ChangePropIfDifferent ich hab das bereinigte Projekt mal angehangen, evtl. hilft das zum Nachvollziehen
    Dateien
    • TicketTimer.zip

      (962,31 kB, 69 mal heruntergeladen, zuletzt: )
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

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

    Eine ObservableCollection hat aber auch ein Event "CollectionChanged" und wenn "Added", "Changed" oder "Removed" im Parameter dann jeweils das machen was man machen will. Und dann eben speichern. Fertig.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Nofear23m schrieb:

    Eine ObservableCollection hat aber auch ein Event "CollectionChanged"


    Ok, das hab ich eingebaut und es funktioniert einwandfrei.
    Bleibt aber noch die Problematik, dass wenn sich in einem Item in der ObservableCollection etwas ändert, nichts davon gespeichert wird. Ich müsste einen Weg finden das Speichern auch zu triggern, wenn sich in einem Ticket, das in der ObservableCollection liegt, ein Wert ändert.


    LG und Danke
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    Wenn du einen Speichern Button hast dann haste ja einen Command, in diesem wird das speichern übernommen.

    Wenn nicht dann machste dur eine Methode und diese rufst du im Setter nach dem OnPropertyChanged auf, dann wird bei jeder änderung des Wertes gespeichert.

    Grüße
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Das Problem hier ist das folgende,
    die Speichern Methode befindet sich Im TicketsViewModel(Sammlung aller Tickets) und ich finde keinen Weg wie ich aus dem TicketViewModel (SingleTicket) (welche sich ja innerhalb der ObservableCollection des TicketsViewModels befinden) die Speichermethode in der Parentklasse TicketsViewModel auslösen kann.

    Einen Speicherbutton gibt es nicht, im Prinzip soll einfach jede Änderung automatisch gespeichert werden. Ziel des ganzen ist, wenn ich meine Anwendung beende, und wieder öffne, soll alles so sein, wie es vor dem Beenden war, ohne dass jemand aktiv speichern müsste oder dergleichen.

    Nachtrag, alternativ würde mir sonst nur einfallen, im TicketsViewModel einen Timer anzulegen, sodass alle paar Sekunden gespeichert wird, das halt ich aber für keine saubere Lösung
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

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

    Lass den Pfusch mit nem Timer. Da gibt es mehrere Lösungen. Um die beste für dich zu finden zeig doch mal wie du die Daten holst oder speicherst. Hast du dir da ein Service gebaut, hast du eine Klasse die das übernimmt wie es sich gehört? Das mpsste ich wissen.

    Grüße
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Die Projektmappe hängt oben in Post7 an.

    Ich verwende einen IDataService in Verbindung mit dem XmlSerializer.

    ITicketsDataService:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. ​Imports System.Collections.ObjectModel
    2. Imports System.IO
    3. Imports System.Text
    4. Imports System.IO.Compression
    5. Public Class TicketsDataService
    6. Implements ITicketsDataService
    7. Public ReadOnly Property GetTickets As ObservableCollection(Of TicketViewModel) Implements ITicketsDataService.GetTickets
    8. Get
    9. If Not File.Exists(Application.SettingsFilePath) Then
    10. Return New ObservableCollection(Of TicketViewModel)
    11. Else
    12. Dim ser As New XmlSerializer()
    13. Return ser.DeSerialize(Of ObservableCollection(Of TicketViewModel))(Application.SettingsFilePath, New ObservableCollection(Of TicketViewModel))
    14. End If
    15. End Get
    16. End Property
    17. Public Sub SaveTickets(Tickets As ObservableCollection(Of TicketViewModel)) Implements ITicketsDataService.SaveTickets
    18. Dim ser As New XmlSerializer()
    19. ser.Serialize(Application.SettingsFilePath, Tickets)
    20. End Sub
    21. End Class


    MainViewModel:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. ​Public Class MainViewModel
    2. Inherits BaseViewModel
    3. Public _TicketDataService As ITicketsDataService
    4. Public Sub New()
    5. _TicketDataService = New TicketsDataService
    6. Tickets = New TicketsViewModel(_TicketDataService)
    7. End Sub
    8. Private _Tickets As TicketsViewModel
    9. Public Property Tickets() As TicketsViewModel
    10. Get
    11. Return _Tickets
    12. End Get
    13. Set(ByVal value As TicketsViewModel)
    14. ChangePropIfDifferent(value, _Tickets)
    15. End Set
    16. End Property
    17. End Class


    TicketsViewModel:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. ​Imports System.Collections.ObjectModel
    2. Imports System.Collections.Specialized
    3. Imports System.ComponentModel
    4. Public Class TicketsViewModel
    5. Inherits BaseViewModel
    6. Private _ticketsservice As ITicketsDataService
    7. Private TicketCounter As Integer = 0
    8. Sub loadTickets()
    9. OpenTickets = _ticketsservice.GetTickets
    10. End Sub
    11. Public Sub savetickets()
    12. _ticketsservice.SaveTickets(OpenTickets)
    13. End Sub
    14. Public Sub New(service As ITicketsDataService)
    15. _ticketsservice = service
    16. OpenTickets = _ticketsservice.GetTickets
    17. loadTickets()
    18. If IsInDesignMode() Then
    19. For I As Integer = 0 To 4
    20. AddTicket()
    21. Next
    22. End If
    23. End Sub
    24. Private WithEvents _OpenTickets As ObservableCollection(Of TicketViewModel)
    25. Public Property OpenTickets() As ObservableCollection(Of TicketViewModel)
    26. Get
    27. Return _OpenTickets
    28. End Get
    29. Set(ByVal value As ObservableCollection(Of TicketViewModel))
    30. ChangePropIfDifferent(value, _OpenTickets)
    31. End Set
    32. End Property
    33. Private _SelectedTicket As TicketViewModel
    34. Public Property SelectedTicket() As TicketViewModel
    35. Get
    36. Return _SelectedTicket
    37. End Get
    38. Set(ByVal value As TicketViewModel)
    39. ChangePropIfDifferent(value, _SelectedTicket)
    40. End Set
    41. End Property
    42. Sub AddTicket()
    43. OpenTickets.Add(New TicketViewModel(TicketCounter + 1))
    44. TicketCounter += 1
    45. End Sub
    46. Sub RemoveTicket()
    47. If SelectedTicket IsNot Nothing Then
    48. OpenTickets.Remove(SelectedTicket)
    49. End If
    50. End Sub
    51. Public ReadOnly Property AddTicketCommand As New RelayCommand(AddressOf AddTicketCommand_Execute)
    52. Private Sub AddTicketCommand_Execute(obj As Object)
    53. AddTicket()
    54. End Sub
    55. Public ReadOnly Property RemoveTicketCommand As New RelayCommand(AddressOf RemoveTicketCommand_Execute, Function(o) SelectedTicket IsNot Nothing)
    56. Private Sub RemoveTicketCommand_Execute(obj As Object)
    57. If MessageBox.Show($"Do you really want to Delete Ticket number {SelectedTicket.NumericalID} from the List?", "Are you sure?", MessageBoxButton.YesNo, MessageBoxImage.Question) <> MessageBoxResult.No Then
    58. RemoveTicket()
    59. End If
    60. End Sub
    61. Private Sub _OpenTickets_CollectionChanged(sender As Object, e As NotifyCollectionChangedEventArgs) Handles _OpenTickets.CollectionChanged
    62. savetickets()
    63. End Sub
    64. End Class


    und TicketViewModel:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. ​Imports System.ComponentModel
    2. Imports System.Timers
    3. Public Class TicketViewModel
    4. Inherits BaseViewModel
    5. Private WorkStopWatch As New Stopwatch
    6. Private WithEvents WorkTimer As New Timer With {.Interval = 5000, .Enabled = False}
    7. Private Sub WorkTimer_Elapsed(sender As Object, e As ElapsedEventArgs) Handles WorkTimer.Elapsed
    8. Runtime = WorkStopWatch.Elapsed
    9. End Sub
    10. Public Sub New()
    11. End Sub
    12. Public Sub New(ByVal NumID As Integer)
    13. NumericalID = NumID
    14. End Sub
    15. Private _TicketText As String = String.Empty
    16. Public Property TicketText() As String
    17. Get
    18. Return _TicketText
    19. End Get
    20. Set(ByVal value As String)
    21. ChangePropIfDifferent(value, _TicketText)
    22. End Set
    23. End Property
    24. Private _Runtime As TimeSpan = TimeSpan.Zero
    25. Public Property Runtime() As TimeSpan
    26. Get
    27. Return _Runtime
    28. End Get
    29. Set(ByVal value As TimeSpan)
    30. ChangePropIfDifferent(value, _Runtime)
    31. End Set
    32. End Property
    33. Private _WorkStart As DateTime?
    34. Public Property WorkStart() As DateTime?
    35. Get
    36. Return _WorkStart
    37. End Get
    38. Set(ByVal value As DateTime?)
    39. ChangePropIfDifferent(value, _WorkStart)
    40. End Set
    41. End Property
    42. Private _WorkEnd As DateTime?
    43. Public Property WorkEnd() As DateTime?
    44. Get
    45. Return _WorkEnd
    46. End Get
    47. Set(ByVal value As DateTime?)
    48. ChangePropIfDifferent(value, _WorkEnd)
    49. End Set
    50. End Property
    51. Private _IsWorking As Boolean
    52. Public Property IsWorking() As Boolean
    53. Get
    54. Return _IsWorking
    55. End Get
    56. Set(ByVal value As Boolean)
    57. ChangePropIfDifferent(value, _IsWorking)
    58. End Set
    59. End Property
    60. Private _NumericalID As Integer = 0
    61. Public Property NumericalID() As Integer
    62. Get
    63. Return _NumericalID
    64. End Get
    65. Set(ByVal value As Integer)
    66. _NumericalID = value
    67. End Set
    68. End Property
    69. Sub SwitchWorkingState()
    70. If Not IsWorking Then
    71. StartWorking()
    72. Else
    73. StopWorking()
    74. End If
    75. End Sub
    76. Sub StartWorking()
    77. WorkStopWatch.Start()
    78. WorkTimer.Start()
    79. If Runtime = TimeSpan.Zero Then
    80. WorkStart = DateTime.Now
    81. End If
    82. IsWorking = True
    83. End Sub
    84. Sub StopWorking()
    85. WorkStopWatch.Stop()
    86. WorkTimer.Stop()
    87. WorkEnd = DateTime.Now
    88. Runtime = WorkStopWatch.Elapsed
    89. IsWorking = False
    90. End Sub
    91. Public ReadOnly Property SwitchWorkingCommand As New RelayCommand(AddressOf SwitchWorkingCommand_Execute)
    92. Private Sub SwitchWorkingCommand_Execute(obj As Object)
    93. SwitchWorkingState()
    94. End Sub
    95. Public ReadOnly Property CopyTicketTextCommand As New RelayCommand(AddressOf CopyTicketTextCommand_Execute)
    96. Private Sub CopyTicketTextCommand_Execute(obj As Object)
    97. Clipboard.SetText(TicketText)
    98. End Sub
    99. End Class
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    Sorry, übersehen, bin mit dem Handy onli e.

    Aber das sieht doch sauber aus.
    Zwei möglichkeiten, entweder du machst dir ein Event in dein TicketViewmodel welches du innerhalb des TicketsViewModel abonnierst oder du reichst die Instanz des TicketService in die TicketViewModel Instanzen rein.

    Bei letzterem hast du hald den Vorteil das du dann zugriff auf diesen hast und z.b. leicht ein Feature wie "Änderungen Rückgängig machen" einbauen kannst.

    Später bin ich beim Rechner und kann dir das zeigen. Lade mal die aktuelle Version hoch (wird sich ja was geändert haben) und dann kann ich dich hier unterstützen.

    Grüße
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Der letztere Ansatz klingt gut, an dem hatte ich mich bereits versucht, bin aber kläglich gescheitert (Beim Laden war die Instanz immer Nothing, das wollte ich umgehen in dem ich beim Laden die Instanz in einer schleife, durch die aktuelle Instanz ersetzt habe, dann kam ich aber irgendwann, bei der Fehlermeldung an, dass ich eine Kreisreferenz ausgelöst habe)

    Anbei die aktuelle Version, viel hatte sich aber nicht geändert ^^ Meist eher kosmetische Anpassungen
    Dateien
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    @Nofear23m

    Ich hab eine Lösung gefunden, nur ob die gut ist weiß ich nicht. Ich hab in der Application.xaml den Dataservice Instanziert, ebenso habe ich das TicketsViewModel, das ja zuvor im MainViewModel instanziert wurde, auch in der Apllication.xaml instanziert. Laden und speichern findet jetzt im Application_Startup bzw. Application_Exit statt.

    Im MainViewModel geb ich jetzt einfach die Application.Tickets als Ticketsviewmodel weiter. Rein vom Verhalten der App läuft jetzt alles so wie gewünscht. hab auch das Projekt mal angehangen, falls meine Erklärung nicht ganz nachzuvollziehen war.


    LG
    Dateien
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    Hallo

    Als erstes muss ich dich unbedingt darauf aufmerksam machen das dein Upload gegen die Forenregeln verstößt. Bitte unbedingt immer vorher den bin und obj Ordner löschen vor dem Upload damit keine ausführbaren Files vorhanden sind.
    Außerdem wird der Upload dadurch kleiner.

    Ich habe mir das angesehen. Soweit sieht das auch gut aus. Sauber aufgebaut. Schaut aus als kommst du auf den Geschmack von MVVM. Da du beim speichern die ObservableCollection mit übergeben musst welche er speichern soll musste ich etwas umbauen.
    Zum einen eher kontraproduktiv, wozu mitgeben wenn das Service die Liste ja kennen kann. Somit reicht es das du im Service dann SaveTickets() aufrufen kannst.
    Eine ObservableCollection im Service ist auch ein wenig zu viel des guten. Habe mal ne List(Of T) daraus gemacht. Besser wäre sogar eine IEnumerable(Of T).

    Da du nicht zwischen Model und ViewModel unterscheidest war es etwas mehr aufwand bei "erstellen" der Objekte aber ist auch im Rahmen.

    Was habe ich gemacht:

    Den Service umgebaut

    VB.NET-Quellcode

    1. Public Class TicketsDataService
    2. Implements ITicketsDataService
    3. Private _aviableTickets As List(Of TicketViewModel)
    4. Public ReadOnly Property GetTickets As List(Of TicketViewModel) Implements ITicketsDataService.GetTickets
    5. Get
    6. If Not File.Exists(Application.SettingsFilePath) Then
    7. Return New List(Of TicketViewModel)
    8. Else
    9. Dim ser As New XmlSerializer()
    10. _aviableTickets = ser.DeSerialize(Application.SettingsFilePath, New List(Of TicketViewModel))
    11. Return _aviableTickets
    12. End If
    13. End Get
    14. End Property
    15. Public Sub SaveTickets(Tickets As List(Of TicketViewModel)) Implements ITicketsDataService.SaveTickets
    16. Dim ser As New XmlSerializer()
    17. ser.Serialize(Application.SettingsFilePath, Tickets)
    18. Debug.WriteLine("SAVED!!")
    19. End Sub
    20. Public Sub SaveTickets() Implements ITicketsDataService.SaveTickets
    21. SaveTickets(New List(Of TicketViewModel)(_aviableTickets))
    22. End Sub
    23. End Class


    Dann im TicketViewModel zum einen eine Methode hinzugefügt über diese man die ServiceInstance setzen kann. Diese wird vom Konstruktor der Klasse aufgerufen, aber auch von "aussen", also vom TicketsViewModel.

    VB.NET-Quellcode

    1. Friend Sub SetServiceInstance(ticketsservice As ITicketsDataService)
    2. _ticketService = ticketsservice
    3. End Sub


    Dann wird folgende Methode jeweils in den Settern der Properties aufgerufen:

    VB.NET-Quellcode

    1. Private Sub SaveTicket()
    2. If _ticketService IsNot Nothing Then
    3. _ticketService.SaveTickets()
    4. End If
    5. End Sub


    Ab nun kann jedes Ticket für sich selbst die Daten speichern.
    Hierbei ist aber nun darauf zu achten das nicht bei jeder kleinen Änderung der Setter aufgerufen wird.
    Z.b. hattest du im Binding UpdateSourceTrigger=PropertyChanged was in diesem Fall nicht so dolle ist wenn bei jeden Buchstaben gespeichert wird.

    OK, nun zum TicketsViewModel:
    Im Konstruktor wird erstmal nur ne leere ObservableCollection erstellt. und loadTickets() aufgerufen.
    Da wirds interessant. Erstmal falls nicht der Fall, die Liste leeren, dann lade ich die Tickets als List(Of T).

    Nun gehe ich die Einträge durch und erstelle ein neues Objekt zu hinzufügen, doch vorher übergebe ich die Instanz des Service.

    VB.NET-Quellcode

    1. Sub loadTickets()
    2. OpenTickets = New ObservableCollection(Of TicketViewModel) 'Leere Observable erstellen
    3. Dim tickets = _ticketsservice.GetTickets() 'Tickets laden
    4. tickets.ForEach(Sub(x) CreateTicketInstance(x)) 'Die Objekte inkl. aktueller TicketService-Instanz hinzufügen
    5. End Sub
    6. Private Sub CreateTicketInstance(x As TicketViewModel)
    7. x.SetServiceInstance(_ticketsservice)
    8. OpenTickets.Add(x)
    9. End Sub
    10. Public Sub savetickets()
    11. _ticketsservice.SaveTickets()
    12. End Sub
    13. Public Sub New(service As ITicketsDataService)
    14. _ticketsservice = service
    15. OpenTickets = New ObservableCollection(Of TicketViewModel)
    16. loadTickets()
    17. If IsInDesignMode() Then
    18. For I As Integer = 0 To 4
    19. AddTicket()
    20. Next
    21. End If
    22. End Sub


    Das ist es dann auch schon. Kann man sicher noch schöner aufbauen, aber fürs Verständnis sollte das passen.

    Grüße
    Sascha

    Edit wegen deiner letzten Antwort (erst jetzt gesehen):
    Du hast das Projekt recht sauber aufgebaut, das klingt nun aber mehr nach Workaround als nach "implementierung". ;)
    Dateien
    • TicketTimer.zip

      (153,27 kB, 66 mal heruntergeladen, zuletzt: )
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Hm, erhalte beim Ausführen leider eine Fehlermeldung:


    Nachtrag: Ich kann auch nicht nachvollziehen, woher der IDataService denn jetzt die Liste kennt, wenn ich die nicht mit übergebe? ?(?(


    Nachtrag2:
    ​Als erstes muss ich dich unbedingt darauf aufmerksam machen das dein Upload gegen die Forenregeln verstößt.

    Ok mach ich in Zukunft, hab bisher einfach die .exe-Dateien gelöscht
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

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

    Der Parameter ist entweder die Startkapazität oder die Elemente, die der Liste von Beginn an hinzugefügt werden sollen. Wenn letzteres null/Nothing ist, gibt's Ärger. Steht auch in der Doku.

    btw: available, nicht aviable
    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.
    Oh, da muss was mit den Files passiert sein. Ich pack dann gleich noch ein Zip und stells ein. Da passt was nicht!!
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##