WPF Textblock während einer Methode mehrfach aktualisieren

  • WPF

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von magicneo.

    WPF Textblock während einer Methode mehrfach aktualisieren

    Hallo zusammen,

    mein Problem ist folgendes:
    Ich habe eine Methode, die recht lange dauert - mehrere Minuten oder sogar noch länger.
    Währen die Methode läuft möchte ich den Anwender über z.B. den Text eines Textblock informieren.
    Ich habe bisher mit Forms gearbeitete. Da gab es die Methoden "Refresh" oder "Update", mit denen ich eine Form zwischendurch aktualisieren konnte (rendern heißt das glaub in der Fachsprache).
    Jetzt muss ich dieses mal mit WPF arbeiten. Da gibt es diese beiden Funktionen nicht.

    Wie kann ich das realisieren?

    Ich suche schon länger nach ner Lösung, hab diverse Foren gewälzt - auch schon eine Lösung gefunden (mit dem Dispatcher), die aber nicht zuverlässig funktioniert.

    Da ich schon lange daran rummache würde ich mich über ne Lösung riesig freuen.

    magic

    PS es geht nicht darum, dem Parameter "Text" eines Textblock einen neuen Wert zuzuweisen - z.B. über ein Binding - sondern er soll es auch sofort anzeigen.
    Da ich schon lange daran rummache
    Von der Formulierung her nicht so toll.

    Was ist an deiner anderen Lösung so unzuverlässig? Alleine mit "Unzuverlässig" kann ich nichts anfangen. Mach doch am besten ein Video und binde es mit einer Control ein.

    So, das waren meine Fragen.

    Grüße, ExteNesia.de

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ExteNesia.de“ ()

    Methode asynchron ausführen. Wie du das machst ist dir überlassen. Gibt es viele Möglichkeiten, Tasks wären wahrscheinlich zu preferieren.
    Gui über Dispatcher Invoke.


    Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.

    ExteNesia.de schrieb:

    Was ist an deiner anderen Lösung so unzuverlässig?


    Unzuverlässig bedeuted, dass es beim ersten Mal funktioniert und bei einem weitern Mal nicht mehr.

    thefiloe schrieb:

    Gui über Dispatcher Invoke.


    Ich vermute, dass Du sowas damit meinst:

    VB.NET-Quellcode

    1. Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, New DispatcherOperationCallback(AddressOf my_callback), my_frame)
    2. Dispatcher.PushFrame(my_frame)


    Das habe ich probiert. Das funktioniert auch sehr gut, wenn ich es innerhalb der langen Methode 1 Mal aufrufe.
    Verwende ich es ein 2. Mal oder noch öfter, funktioniert es nicht mehr. Das verstehe ich nicht und habe auch noch keine Lösung dafür.

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

    thefiloe schrieb:

    Gibt es viele Möglichkeiten, Tasks wären wahrscheinlich zu preferieren.
    Gui über Dispatcher Invoke.
    ich würd fürs Gui eher die Progress(Of T) - Klasse bemühen - ist glaub im weiteren Sinne Bestandteil des Tasking-Konzepts.
    Dabei würde die Progress-Klasse auch garnix mittm Gui zu tun haben, sondern würde - ganz nach MVVM - einfach das Viewmodel updaten - und die Bindings - wie gehabt - machen ihren Job, und updaten das Gui.
    Hallo ErfinderDesRades,

    ErfinderDesRades schrieb:

    und die Bindings - wie gehabt - machen ihren Job, und updaten das Gui.


    Meine Erafhrung ist die, dass die Bindings zwar - "simple gesagt" - z.B. den Wert des Parameters Text eines Textblocks updaten - d.h. aber noch lange nicht, dass der geänderte Inhalt auch genau in diesem Moment so geändert angezeigt wird. Das passiert erst, wenn die Methode beendet ist. Und genau das ist ja mein Problem. Der geänderte Wert soll sofort angezeigt werden. Und das mehrfach hintereinander innerhalb einer Methode. So, wie es bei den Forms mit "Refresh" so schön einfach ist.

    ErfinderDesRades schrieb:

    ich würd fürs Gui eher die Progress(Of T) - Klasse bemühen


    Meinst Du sowasin der Art (der Textblock1 meines Windows soll den Text "Honda" anzeigen) ? :

    VB.NET-Quellcode

    1. Private Async Sub Sample()
    2. Dim progressHandler = New Progress(Of String)(Sub(value) Me.Textblock1.Text = value)
    3. Dim progress = TryCast(progressHandler, IProgress(Of String))
    4. Await Task.Run(Sub() progress.Report("Honda"))
    5. End Sub


    Funktioniert leider auch nicht so, wie ich das gerne hätte.

    Viele Grüße

    magic

    magicneo schrieb:

    Meine Erafhrung ist die, dass die Bindings zwar - "simple gesagt" - z.B. den Wert des Parameters Text eines Textblocks updaten - d.h. aber noch lange nicht, dass der geänderte Inhalt auch genau in diesem Moment so geändert angezeigt wird.
    Das scheint eine Erfahrung ohne Threading zu sein.
    Bei Threading würde deine langlaufende Methode im NebenThread laufen, und könnte gelegentlich auch ein Updaten des Guis anstoßen. Welches dann im MainThread stattfindet, vlt. eine Millisekunde später.
    Ist vollkommen ohne Belang, wann das Gui den neuen Wert anzeigt - ob 1ms oder 5ms später - dein Langläufer läuft eh weiter auf seiner Bahn - ob und was das Gui anzeigt ist für ihn nicht massgeblich.



    Zu deim Sample:
    Prinzipiell richtig, aber es ist keine langlaufende Methode enthalten, deswegen kann der Code ja nur Unsinn machen.
    Also eine Methode, die einen Task erzeugt, der nichts anderes macht, als eine weitere Methode dann wieder an den MainThread zu delegieren - das ist Unsinn, denn da kann man die weitere Methode auch gleich im Mainthread aufrufen.

    Ach - vlt. wäre so sinniger:

    VB.NET-Quellcode

    1. Private WithEvents _Progress As New Progress(Of String)
    2. Private Async Sub Sample()
    3. UpdateGui(Nothing, "before LonglastingMethod")
    4. Await Task.Run(AddressOf LongLastingMethod)
    5. UpdateGui(Nothing, "after LonglastingMethod")
    6. End Sub
    7. Private Sub LongLastingMethod()
    8. For i = 0 To 9
    9. Threading.Thread.Sleep(500)
    10. DirectCast(_Progress, IProgress(Of String)).Report("Honda" & i)
    11. Next
    12. End Sub
    13. Private Sub UpdateGui(sender As Object, e As String) Handles _Progress.ProgressChanged
    14. Me.Textblock1.Text &= e & Lf
    15. End Sub
    beachte, dass das Gui responsiv bleibt, währen LonglastingMethod läuft