web-dev-qa-db-fra.com

Bouton désactiver et activer

J'ai une application Windows basée sur vb.net, où, lorsque vous cliquez sur le bouton "GO", un groupe de données est chargé dans la base de données. Donc, dans mon application, dès que le bouton "GO" est cliqué, je veux simplement le désactiver et le réactiver une fois le téléchargement terminé . Maintenant, dans ma méthode spécifique pour btnGo_Click (), j'ai:

btnGo.Enabled = False

en première ligne et 

btnGo.Enabled = True

comme dernière ligne de la même méthode.

Mais je ne parviens pas à comprendre pourquoi le "GO" apparaît comme étant désactivé étant toujours autorisé à cliquer lorsque le traitement est en cours. De plus, si je supprime la dernière ligne, elle est désactivée de manière permanente et n'autorise pas l'événement click.

Suggérez ce que je fais mal

Edit (25 janvier 2012): J'ai apporté les modifications suggérées par nos collègues, mais je suis confronté à un nouveau problème ici. Je suis confronté à un problème où la zone de texte est mise à jour mais pas toujours. J'ai mis à jour ma zone de texte dans l'événement "_ProgressChanged" du thread de travail en arrière-plan. Dans mon cas, il y a 10 enregistrements téléchargés. Ensuite, 10 lignes de mises à jour sont attendues dans la texbox. Mais seules quelques lignes apparaissent dans la zone de texte. Est-ce le problème de repeindre à nouveau? Suggérez gentiment ... Parce que toutes les autres choses sont faites selon votre suggestion

9
Justin Samuel

Vous ne faites rien de mal. Le problème est que l'interface utilisateur n'est pas mise à jour tant que le code à l'intérieur de votre méthode de gestionnaire d'événements n'a pas fini de s'exécuter. Ensuite, le bouton est désactivé et immédiatement activé en séquence rapide.

Cela explique pourquoi si vous oubliez de réactiver le contrôle de bouton à la fin de la méthode du gestionnaire d'événements, il est toujours désactivé, car vous lui avez dit de désactiver le bouton dans la première ligne de la méthode.

Ceci est un cas classique de la raison pour laquelle vous ne devriez jamais effectuer de tâches de calcul de longue durée à l'intérieur d'une méthode de gestionnaire d'événements, car elle empêche la mise à jour de l'interface utilisateur. Le calcul doit en réalité être effectué sur un thread séparé. Mais n'essayez pas de créer le fil manuellement, et surtout n'essayez pas de mettre à jour votre interface utilisateur à partir d'un thread séparé. Au lieu de cela, utilisez le composant BackgroundWorker pour gérer tout cela automatiquement pour vous. La documentation MSDN liée contient un excellent exemple d'utilisation.

Désactivez le bouton avant de démarrer BackgroundWorker, puis réactivez-le dans son événement Completed, signalant l'achèvement du chargement de votre base de données.

15
Cody Gray

Puisque vous essayez d’exécuter une fonction qui peut prendre un certain temps, je vous conseillerais d’utiliser le threading. Dans .NET, il existe un composant BackgroundWorker qui est excellent pour l'exécution de tâches asynchrones. 

En cliquant sur le bouton, appelez BackgroundWorker comme suit:

if not bgwWorker.IsBusy then
   btnGo.enabled = false
   bgwWorker.RunWorkerAsync()
end if 

Et utilisez l'événement terminé pour réactiver le bouton:

Private Sub bgwWorker_DoWork(ByVal sender As System.Object, _
                 ByVal e As System.ComponentModel.DoWorkEventArgs) _
                 Handles bgwWorker.DoWork
' Do your things    
End Sub

Private Sub bgwWorker_RunWorkerCompleted(ByVal sender As System.Object, _
                         ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
                         Handles bgwWorker.RunWorkerCompleted
' Called when the BackgroundWorker is completed.
btnGo.enabled = true
End Sub

Dans l'exemple ci-dessus, j'ai utilisé bgwWorker en tant qu'instance d'un BackgroundWorker.

3
Rhapsody

Si votre btnGo_Click() est exécuté dans le thread principal, l'interface utilisateur ne peut pas être mise à jour correctement dans une tâche fastidieuse.
La meilleure façon de faire ce dont vous avez besoin est d’exécuter votre méthode dans un fichier BackgroundWorker

0
Marco

Ce n'est généralement pas une bonne idée de gérer l'état d'un bouton de soumission. Au lieu de cela, effectuez la validation sur soumettre.

0
LastTribunal

Je viens d'essayer de désactiver un bouton, Updateing du formulaire, Sleeping et de l'activer à nouveau. Il a quand même effectué le clic (un clic qui a été fait alors qu'il "dormait" avec le bouton désactivé) après l'avoir activé.

Je suppose que les formulaires "se souviennent" des clics.

(EDIT: je l'ai fait en C #.)

0
ispiro

L'événement clic sur le bouton est géré dès que le thread d'interface utilisateur a un temps d'inactivité. Après avoir désactivé votre bouton, le fil de l'interface utilisateur est occupé par votre code. À la fin de votre méthode, vous réactivez le bouton, puis vous quittez la méthode et laissez un temps d'inactivité. En conséquence, le bouton sera déjà activé au moment où l'événement click est géré, votre clic est donc "reconnu". 

La solution consiste, comme l'ont déjà suggéré d'autres personnes, à utiliser un Backgroundworker. 

N'essayez pas d'utiliser doEvents () comme solution (ne le faites jamais), car cela risquerait de poser d'autres problèmes subtils. Cela dit, vous pouvez prouver l’explication ci-dessus avec des événements expérimentaux dans votre code. Vous verrez que le clic est supprimé si un événement DoEvents est effectué avant que le bouton ne soit réactivé. Par ailleurs, effectuer un événement doEvents directement après le fichier button.disable (pour "mettre à jour l'interface graphique") ne vous aidera pas s'il est exécuté avant le clic.

0
Timm