Comment puis-je actualiser les propriétés de contrôle visuel (TextBlock.text) définies dans une boucle?
À chaque itération de boucle je veux visuellement mise à jour le texte d'un textblock. Mon problème est que la fenêtre WPF ou de contrôle n'est pas visuellement de rafraîchissement jusqu'à ce que la boucle est terminée.
for (int i = 0; i < 50; i++)
{
System.Threading.Thread.Sleep(100);
myTextBlock.Text = i.ToString();
}
En VB6, je voudrais appeler la fonction DoEvents() ou de contrôle.actualiser. Pour le moment je voudrais juste un moyen rapide et sale solution similaire à la fonction DoEvents(), mais j'aimerais aussi savoir sur les solutions de rechange ou de la "bonne" façon de faire. Est-il une liaison simple déclaration, je pourrais ajouter? Quelle est la syntaxe?
Merci à l'avance.
source d'informationauteur DeveloperDan
Vous devez vous connecter pour publier un commentaire.
Si vous vraiment veux du rapide et sale de la mise en œuvre et ne se soucient pas de maintenir le produit à l'avenir ou à propos de l'expérience de l'utilisateur, vous pouvez simplement ajouter une référence à System.De Windows.Formes et appel
System.Windows.Forms.Application.DoEvents()
:L'inconvénient est que c'est vraiment vraiment mauvais. Vous allez à verrouiller l'INTERFACE utilisateur au cours de la discussion.Sleep(), qui agace les utilisateurs, et vous pouvez vous retrouver avec des résultats imprévisibles en fonction de la complexité du programme (j'ai vu une application où les deux méthodes ont été en cours d'exécution sur le thread de l'INTERFACE utilisateur, chacun appelant la fonction DoEvents() à plusieurs reprises...).
C'est comment il devrait être fait:
Voici un exemple montrant la fonctionnalité que vous avez demandé. Il ne prend que quelques secondes de plus à écrire et c'est tellement plus facile de travailler avec et il n'a pas de verrouillage de l'INTERFACE utilisateur.
Xaml:
Le code-behind:
Le code peut sembler un peu compliqué, mais c'est une pierre angulaire de WPF, et il est livré avec un peu de pratique, c'est bien la peine d'apprendre.
C'est comment vous le feriez normalement:
Cette délégués de l'opération à un travailleur de pool de threads, ce qui permet à votre thread d'INTERFACE utilisateur pour traiter les messages (et maintient votre INTERFACE utilisateur à partir de zéro). Parce que le thread ne peut pas accéder à
myTextBlock
directement, il doit utiliserBeginInvoke
.Bien que cette approche n'est pas "le WPF façon" de faire les choses, il n'y a rien de mal à cela (et en effet, je ne crois pas qu'il existe une alternative avec ce petit code). Mais une autre façon de faire les choses iraient comme ceci:
Text
de laTextBlock
à une propriété d'un objet qui implémenteINotifyPropertyChanged
BeginInvoke
ou quoi que ce soit d'autreSi vous disposez déjà d'un objet et l'INTERFACE utilisateur a accès, c'est aussi simple que l'écriture
Text="{Binding MyObject.MyProperty}"
.Mise à jour: Par exemple, supposons que vous avez ceci:
La liaison serait fait comme ceci dans le code XAML:
J'ai essayé la solution exposée ici, et ça n'a pas fonctionné pour moi jusqu'à ce que j'ai ajouté ce qui suit.
Créer une méthode d'extension et assurez-vous de référence contenant l'assemblage de votre projet.
Ensuite l'appeler juste après RaisePropertyChanged.
Qui force l'UIThread de prendre le contrôle pour les petits tout et expédier les modifications en attente sur le UIElement.
Vous pouvez faire Répartiteur.BeginInvoke afin de faire un thread contexte-commutateur, de sorte que le thread de rendu pourrait faire son travail.
Cependant, ce n'est pas la bonne façon de faire pour ces choses. Vous devriez utiliser l'Animation + de Liaison pour des choses comme ça, comme c'est le hack de façon libre de faire ce genre de choses dans WPF.
Exécute le code ci-dessus à l'intérieur d'un contexte travailleur composant et à l'aide d'une liaison updatesourcetrigeer comme propertychanged reflètent les modifications immédiatement dans l'INTERFACE utilisateur de contrôle