DispatcherTimer MVVM-konform machen

  • WPF MVVM

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von Nofear23m.

    DispatcherTimer MVVM-konform machen

    Erstmal schönes Wochenende euch allen :)

    Ich möchte mit einem DispatcherTimer arbeiten und habe schon folgendes:

    VB.NET-Quellcode

    1. Private Sub TimerStarten()
    2. Dim MeinTimer = New DispatcherTimer()
    3. MeinTimer.Interval = TimeSpan.FromSeconds(1)
    4. AddHandler MeinTimer.Tick(), AddressOf MeinTimer_Tick
    5. End Sub
    6. Private Sub MeinTimer_Tick(ByVal sender As Object, ByVal e As EventArgs)
    7. [...]
    8. End Sub


    Aber das ist ja glaube ich vorne und hinten nicht MVVM-konform (das Event?)??

    Mal abgesehen funktioniert es nicht. Das MeinTimer.Tick() in Zeile 4 wird rot unterstrichen mit der Meldung:
    Der AddHandler- oder RemoveHandler-Anweisungsereignisoperand muss ein punktqualifizierter Ausdruck oder ein einfacher Name sein.

    Wie löse ich das am besten? Keine Ahnung wie ich da rangehen soll...
    Das Fehlerproblem ist schnell gelöst: Lass die Klammern weg.
    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.
    @kafffee
    Jetzt nimmst du uns aber dann schon auf den Arm oder?

    MVVM und dann bekommt du einen EventHandler nicht hin. OK, wenn man noch nie was damit zu tun hatte weis man es nicht, aber es gibt ja etwa 394.495 Beispiele im Netz.

    Aber nun zu deiner Frage:
    Doch, das ist MVVM konform, du holst ja die View nichts ins ViewModel. Die Layer bleiben entkoppelt solange im "Timer-Tick" nur Properties manipuliert werden (wenn überhaupt).
    Also alles gut.

    Ich persönlich würde nur eher zu einem System.Timer.Timer greifen als zu einem System.Dispatcher.Timer.
    Mit dem DispatcherTimer wirst du Probleme bekommen, die zeigen sich aber erst.

    Hier ein Beispiel für dich:

    VB.NET-Quellcode

    1. ​Public Class MainViewModel
    2. Inherits Instrastructure.ViewModelBase
    3. Private workerTimer As Timer
    4. Public Sub New()
    5. Debug.WriteLine($"{DateTime.Now.ToLongTimeString()}: Constructor fo class {Me.GetType().Name}")
    6. StartTimer()
    7. End Sub
    8. Private _currentTime As String
    9. Public Property CurrentTime() As String
    10. Get
    11. Return _currentTime
    12. End Get
    13. Set(ByVal value As String)
    14. _currentTime = value
    15. RaisePropertyChanged()
    16. End Set
    17. End Property
    18. Private Sub CreateTimerObject()
    19. workerTimer = New Timer()
    20. workerTimer.Interval = 5 * 1000
    21. AddHandler workerTimer.Elapsed, AddressOf Timer_Elapsed
    22. Debug.WriteLine($"{DateTime.Now.ToLongTimeString()}: Timer was initialized")
    23. End Sub
    24. Private Sub StartTimer()
    25. If workerTimer Is Nothing Then CreateTimerObject()
    26. workerTimer?.Start()
    27. Debug.WriteLine($"{DateTime.Now.ToLongTimeString()}: Timer was started")
    28. End Sub
    29. Private Sub StopTimer()
    30. workerTimer?.Stop()
    31. workerTimer.Dispose()
    32. Debug.WriteLine($"{DateTime.Now.ToLongTimeString()}: Timer stopped")
    33. End Sub
    34. Private Sub Timer_Elapsed(sender As Object, e As ElapsedEventArgs)
    35. Debug.WriteLine($"{DateTime.Now.ToLongTimeString()}: Timer elapsed")
    36. CurrentTime = $"{DateTime.Now.ToLongDateString} {DateTime.Now.ToLongTimeString}.{DateTime.Now.Millisecond}"
    37. End Sub
    38. End Class


    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. ##

    Richtig, für den einen ein Nachteil für den anderen ein Vorteil, wie man es sieht.
    Mein Beispiel funktioniert allerdings bei Binding.

    Da der TE allerdings ja wie wir wissen so einen Musikplayer macht denke ich das er hier in folge weniger Probleme damit hat, aber das ist sicher Geschmacksache.
    Welchen er wählt muss er am ende eh selbst entscheiden.
    Welchen würdest du nehmen und warum? Interessiert mich irgendwie da ich auch immer vor der Entscheidung stehe.

    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. ##

    na, einen der im Gui-Thread läuft.
    Ich glaub, DispatcherTimer tut das - würde ich aber erstmal überprüfen.
    In meiner Architektur habichs üprüft - da haut das hin.
    Nebenläufigkeit fasse ich nur an, wenn ichs wirklich brauche.
    Ja, die meisten Bindings sind threadsicher, aber ich glaub ich hatte mal Fails, als ich eine ICollectinoView gebunden hab, deren DataSource im NebenThread Zufügungen erhielt.
    Weiters gefällt mir das irgendwie nicht, dass dann bei jedem PropertyChanged intern auch noch ein ISynChronisize.Invoke abläuft.
    Ich weis auf was du hinaus willst. Ja, ObservableCollections sind auch nicht Thread-Safe. Hier muss man Invoken.
    Das nehme ich hald gerne in Kauf, denn in den meisten Fällen (in meinen zumindest) läuft in einem Timer etwas ab was im Hintergrund etwas prüft oder Daten validiert, da ist es sehr häufig nicht mal notwendig die UI zu aktualisieren, und das will ich dann eben nicht im UI Thread haben.

    Ich gehe auch immer mehr dazu über alles was geht Asyncron laufen zu lassen. Dank Async/Await ist das ja super easy geworden.
    Ich habe mittlerweile auch ein MVVM Konzept um ViewModel-Konstruktoren quasi asyncron laufen zu lassen, das ist ein echter Game-Changer und verbessert das UX extrem.
    Das ist der Grund warum ich immer mehr weg vom UI - Thread delegieren will.

    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. ##