none
kein update Statusbar in WPF Applikation RRS feed

  • Frage

  • Hallo,

    Ich möchte während der Programmausführung die Statusbar updaten, allerdings sehe ich das update erst nach Beendigung des Programmablaufs:

    Ich rufe das update mit folgender Funktion auf:

    private void UpdateStatus(string message)
            {
                Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
                {
                    this.calc_step.Text = message;
                }));
            }

    Gibt es da einen Trick?

    Besten Dank!

    Andreas

    Sonntag, 31. Januar 2016 07:47

Antworten

  • Hallo Andreas,

    ob alles im selben Namespace liegt ist egal, die Frage ist ob alles im selben Thread ausgeführt wird. Also ob du irgendwo mal async/await, Thread, Backgroundworker oder Task eingesetzt hast.

    Das einfachste ist das async/await Pattern ab C# 5. Wenn du bisher kein bischen Asynchronen Code hast, den du aber für die UI Aktualisierung brauchst, dann empfehle ich dir diesen Artikel in der MSDN durchzulesen. Damit bekommst du einen kurzen Überblick und kannst dann beispielsweise deine Eventhandler sehr einfach asynchron gestalten. Bedenke aber, dass dann jeder UI-Zugriff über den Dispatcher laufen muss.


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    • Als Antwort markiert AndiBitti Sonntag, 31. Januar 2016 18:26
    Sonntag, 31. Januar 2016 09:57
    Moderator
  • Hi Andreas,
    das Zauberwort heißt MVVM. Die Idee darin ist, dass es kein Codbehind gibt bzw. dieser nur minimalistisch ausgebaut wird (in Abweichung zum "reinen" MVVM). De gesamte Geschäftslogik wird in einen ViewModel ausgelagert, deren Daten, die in der Ansicht genutzt werden, als Eigenschaften im ViewModel enthalten sind. Die Ansicht (XAML) ist dann nur per Binding mit den Eigenschaften der ViewModel-Instanz verbunden. Wenn der ViewModel Daten ändert, egal wer der Verursache ist, dann wird mit INotifyPropertyChanged dies der Oberfläche indirekt mitgeteilt, die sich dann die aktuellen Daten aus der ViewModel-Instanz holt. Verursacher der Datenänderung können auch asynchrone Prozesse (threads) sein, die dann mittels Dispatcher diese Änderungen der Werte in den Eigenschaften ausführen. Mit diesen asynchronen Prozessen kann die Belastung der Oberfläche von der Verarbeitung entkoppelt werden und die Oberfläche wird immer sofort aktualisiert und reagiert auch immer auf Benutzeraktivitäten.

    Wenn Du jetzt alles im CodeBehind hast, dann kopiere von dort alles in eine separate Klasse (ViewModel) und baue die Bindungen auf. Das bedeutet, in der Oberfläche "{Binding ...}" und im ViewModel Eigenschaften. Für Ereignisse, die der Bediener auslöst (Buttons usw.) nutzt Du für die Bindung eine RelayCommand-Klasse. Die meisten anderen Ereignisse kann man indirekt über Änderungen der Collections abfangen. Für den seltenen Fall besonderer Ereignisse der Oberfläche kannst Du ein angehängtes Verhalten (attached behavior) nutzen.

    Zum Schluss der Umstellung, die bestimmt einige Zeit in Anspruch nimmt, kannst Du ein sauber strukturiertes Projekt haben, was dann auch gut wartbar ist. Für den Übergang ist es auch möglich, nicht gleich den gesamten CodeBehind auszulagern, sondern den Codebehind erst einmal als DataContext zu setzen und schrittweise die Bindungen aufzubauen. Dabei kann man alle erfolgreichen Bindungen schrittweise in einen ViewModel auslagern, dessen Instanz dann als DataContext gesetzt wird.


    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen!
    Schüler sagen, Lehrer haben es gut.
    Schüler, sagen Lehrer, haben es gut


    • Bearbeitet Peter Fleischer Sonntag, 31. Januar 2016 10:00
    • Als Antwort markiert AndiBitti Sonntag, 31. Januar 2016 18:29
    Sonntag, 31. Januar 2016 09:59

Alle Antworten

  • Hi Andreas,
    vermutlich ist der UI Thread zu 100% ausgelastet, so dass kein Refresh der Oberfläche möglich ist. Kannst Du das mal prüfen bzw. zeigen, was im Code des UI Threads gemacht wird und wie der andere thread, aus dem Du den Dispatcher aufrufst gestaltet ist.

    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen!
    Schüler sagen, Lehrer haben es gut.
    Schüler, sagen Lehrer, haben es gut

    Sonntag, 31. Januar 2016 08:52
  • Hallo Peter, Besten Dank für Deine Antwort. Mein Projekt war ursprünglich etwas kleiner geplant. Somit befürchte ich was Du oben beschrieben hast. Alle Funktion befinden sich im Namespace des Fensters in dem ich die Statusbar aktualisieren möchte. Gibt es einen workaround für diese "architektonische" Krise. Übrigens dieses Projekt ist kein kommerzielles Projekt, sondern ist nur ein Tool zur Bearbeitung meiner Dissertation. Besten Dank! Andreas
    Sonntag, 31. Januar 2016 09:35
  • Hallo Andreas,

    ob alles im selben Namespace liegt ist egal, die Frage ist ob alles im selben Thread ausgeführt wird. Also ob du irgendwo mal async/await, Thread, Backgroundworker oder Task eingesetzt hast.

    Das einfachste ist das async/await Pattern ab C# 5. Wenn du bisher kein bischen Asynchronen Code hast, den du aber für die UI Aktualisierung brauchst, dann empfehle ich dir diesen Artikel in der MSDN durchzulesen. Damit bekommst du einen kurzen Überblick und kannst dann beispielsweise deine Eventhandler sehr einfach asynchron gestalten. Bedenke aber, dass dann jeder UI-Zugriff über den Dispatcher laufen muss.


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    • Als Antwort markiert AndiBitti Sonntag, 31. Januar 2016 18:26
    Sonntag, 31. Januar 2016 09:57
    Moderator
  • Hi Andreas,
    das Zauberwort heißt MVVM. Die Idee darin ist, dass es kein Codbehind gibt bzw. dieser nur minimalistisch ausgebaut wird (in Abweichung zum "reinen" MVVM). De gesamte Geschäftslogik wird in einen ViewModel ausgelagert, deren Daten, die in der Ansicht genutzt werden, als Eigenschaften im ViewModel enthalten sind. Die Ansicht (XAML) ist dann nur per Binding mit den Eigenschaften der ViewModel-Instanz verbunden. Wenn der ViewModel Daten ändert, egal wer der Verursache ist, dann wird mit INotifyPropertyChanged dies der Oberfläche indirekt mitgeteilt, die sich dann die aktuellen Daten aus der ViewModel-Instanz holt. Verursacher der Datenänderung können auch asynchrone Prozesse (threads) sein, die dann mittels Dispatcher diese Änderungen der Werte in den Eigenschaften ausführen. Mit diesen asynchronen Prozessen kann die Belastung der Oberfläche von der Verarbeitung entkoppelt werden und die Oberfläche wird immer sofort aktualisiert und reagiert auch immer auf Benutzeraktivitäten.

    Wenn Du jetzt alles im CodeBehind hast, dann kopiere von dort alles in eine separate Klasse (ViewModel) und baue die Bindungen auf. Das bedeutet, in der Oberfläche "{Binding ...}" und im ViewModel Eigenschaften. Für Ereignisse, die der Bediener auslöst (Buttons usw.) nutzt Du für die Bindung eine RelayCommand-Klasse. Die meisten anderen Ereignisse kann man indirekt über Änderungen der Collections abfangen. Für den seltenen Fall besonderer Ereignisse der Oberfläche kannst Du ein angehängtes Verhalten (attached behavior) nutzen.

    Zum Schluss der Umstellung, die bestimmt einige Zeit in Anspruch nimmt, kannst Du ein sauber strukturiertes Projekt haben, was dann auch gut wartbar ist. Für den Übergang ist es auch möglich, nicht gleich den gesamten CodeBehind auszulagern, sondern den Codebehind erst einmal als DataContext zu setzen und schrittweise die Bindungen aufzubauen. Dabei kann man alle erfolgreichen Bindungen schrittweise in einen ViewModel auslagern, dessen Instanz dann als DataContext gesetzt wird.


    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen!
    Schüler sagen, Lehrer haben es gut.
    Schüler, sagen Lehrer, haben es gut


    • Bearbeitet Peter Fleischer Sonntag, 31. Januar 2016 10:00
    • Als Antwort markiert AndiBitti Sonntag, 31. Januar 2016 18:29
    Sonntag, 31. Januar 2016 09:59
  • Hallo,

    Besten Dank für die schnelle Antwort, hat mir sehr geholfen

    Andreas

    Sonntag, 31. Januar 2016 18:29
  • Hallo Peter,

    Super Hilfe von Euch in diesem Forum.

    Besten Dank!

    Werde beginnen meine Applikation auf das MVVM Modell umzustellen!

    Schönen Gruß,

    Andreas

    Sonntag, 31. Januar 2016 18:31