Wie kann ich aktualisieren Sie visual control-Eigenschaften (TextBlock.text) in einer Schleife?
Mit jeder loop-iteration, möchte ich visuell aktualisieren Sie den text aus einem textblock. Mein problem ist, dass das WPF-Fenster oder Steuerelement nicht optisch auffrischen, bis die Schleife beendet ist.
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
myTextBlock.Text = i.ToString();
}
In VB6, würde ich DoEvents()
oder control.Refresh
. Im moment möchte ich nur eine quick-and-dirty-Lösung ähnlich DoEvents()
, aber ich würde auch gerne wissen, über alternativen oder die "richtige" Art und Weise, dies zu tun. Gibt es eine einfache verbindliche Aussage, die ich hinzufügen könnte? Was ist die syntax?
Vielen Dank im Voraus.
InformationsquelleAutor DeveloperDan | 2011-03-31
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie wirklich wollen die quick-and-dirty-Implementierung und kümmern sich nicht um die Pflege des Produkts in der Zukunft oder über die Benutzer-Erfahrung haben, können Sie einfach fügen Sie einen Verweis auf System.Windows.Formen und rufen
System.Windows.Forms.Application.DoEvents()
:Der Nachteil ist, dass es wirklich wirklich schlecht. Du gehst zu sperren der Benutzeroberfläche während der Thread.Sleep(), das nervt die Nutzer, und Sie könnten am Ende mit unvorhersehbaren Ergebnissen, abhängig von der Komplexität des Programms (die ich gesehen habe eine Anwendung, wo die zwei Methoden ausgeführt wurden, die auf dem UI-thread, jeder Aufruf von DoEvents() wiederholt...).
Dies ist, wie es getan werden sollte:
Hier ist ein Beispiel zeigt die Funktionalität, die Sie gebeten haben. Es dauert nur ein paar Sekunden länger dauern zu schreiben, und es ist so viel einfacher, mit zu arbeiten - und es nicht sperren, bis der Benutzeroberfläche.
Xaml:
CodeBehind:
Den code könnte scheinen ein bisschen kompliziert, aber es ist ein Grundstein von WPF, und es kommt zusammen mit ein bisschen übung - es lohnt zu lernen.
Was ist dieser code Aussehen .net 3.5 (speziell Aufgabe.Factory.StartNew)
Aufgabe.Factory.StartNew eingeführt wurde .net 4. Suchen Sie einfach nach
.net 3.5 threading
zu finden, die legacy-Mechanismen.InformationsquelleAutor Greg Sansom
Ich habe versucht, die Lösung ausgesetzt, und hier ist es für mich nicht funktioniert, bis ich fügte hinzu, die folgenden:
Erstellen Sie eine extension-Methode, und stellen Sie sicher, dass Sie den Verweis auf den mit der Montage aus dem Projekt.
Dann rufen Sie gleich nach
RaisePropertyChanged
:Zwingen den UI-thread die Kontrolle zu übernehmen, für eine kleine Weile und Versand alle ausstehenden änderungen auf die UI-element.
InformationsquelleAutor Jazz
Dies ist, wie Sie es tun würde, in der Regel:
Diese Delegierten die operation zu einem worker-thread-pool, mit dessen Hilfe der UI-thread, um Nachrichten zu verarbeiten (und hält die UI einfrieren). Weil der thread keinen Zugriff
myTextBlock
direkt, es mussBeginInvoke
.Obwohl dieser Ansatz ist nicht "der WPF-Weg", Dinge zu tun, es ist nichts falsch mit ihm (und in der Tat, ich glaube nicht, dass es keine alternative mit diesem kleinen code). Aber einen anderen Weg, Dinge zu tun, die gehen würden, wie diese:
Text
desTextBlock
auf eine Eigenschaft eines Objektes, dieINotifyPropertyChanged
BeginInvoke
oder sonst etwasWenn Sie bereits ein Objekt und die UI zugreifen kann, dies ist so einfach wie das schreiben
Text="{Binding MyObject.MyProperty}"
.Update: Zum Beispiel, nehmen wir an, Sie haben diese:
Die Bindung erfolgen würde, wie dies in XAML:
den code auf einen anderen thread nichts tut? Ich denke also, wenn Sie Ihre Benutzeroberfläche eingefroren erstreckt sich von 100msec zählt als "nichts".
aber das war nicht die Frage, und es ist ziemlich offensichtlich...
+1 für die 3 Stufen in den zweiten Teil deiner Antwort. das funktioniert perfekt und ist sehr einfach zu implementieren. Dies ist ein wesentlicher Teil des MVVM als gut.
Während Ihr code-Beispiel funktioniert gut, es ist zu Komplex für mich, um zu erinnern. Was verbindliche syntax könnte ich für diese.MyProperty? Meine quick-and-dirty-Formular ist nur mit code-behind - keine externe Objekte. Ich habe nicht bekommen, die verbindliche syntax Recht. Wie kann ich ersetzen Sie Ihre MyObject.MyProperty mit einer verbindlichen Anweisung, verweist auf eine Eigenschaft auf meine WPF-Fenster? Statt der Einstellung myTextBlock.text direkt würde ich ein update der Window-Eigenschaft, die wiederum würde zu aktualisieren, die gebundenen textblock.text.
InformationsquelleAutor Jon
Können Sie tun Dispatcher.BeginInvoke, um zu tun, einen thread-context-switch, so dass der rendering-thread könnte seinen job tun.
Dies ist jedoch nicht der richtige Weg für solche Dinge. Sie sollten mit Animation + Bindung für Dinge wie, dass, wie das ist, die hack-freie Weise, Dinge zu tun, wie das in WPF.
Ich bitte zu unterscheiden. Animation kann das auch. das einzige, was u tun müssen, ist die Umsetzung einer DP, wo u wollen, dass die animation an.
Sie binden können, um eine Eigenschaft und verwenden Sie einen geeigneten Konverter zu bringen, über UI-änderungen, sicher. Wo kommt die animation kommen?
Sie animieren die DP. das Textfeld gebunden werden, dass DP.
Warum würden Sie ihn animieren, wenn Sie es wollen, zu reflektieren den Zustand eines Prozesses?
InformationsquelleAutor Elad Katz
Ausführen der oben genannten code in einem hintergrund-worker-Komponente und eine Bindung
updatesourcetrigeer
alspropertychanged
werden die änderungen sofort in der UI-Steuerelement.InformationsquelleAutor Padmanaban