Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Membre à l'essai
    Comment désactiver réellement un bouton sous C# Winforms
    Bonjour,

    Avec C# winforms, j'essaie de créer une petite application, et j'essaie de désactiver un bouton après avoir cliqué dessus.
    Pour désactiver le bouton, j'utilise la ligne suivante :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    button.Enabled = false;


    mais je me rends compte que le bouton est grisé mais pas désactivé car quand je clique dessus, il relance le traitement.

    Comment désactiver réellement un bouton sous C# winforms ?

    Merci.

  2. #2
    Expert éminent sénior
    Ajoute button.refresh ou application.doevents après enabled = false et avant le traitement
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Expert éminent
    Surprenant comme comportement.

    Dans quel cas cela se produit-il ?

    Comment est géré le code déclenché par l'appui sur le bouton ?

    Car d'après mes tests, Click n'est jamais déclenché quand le bouton est désactivé, que ce soit lors du clic de la souris, l'appui d'entrée lorsque le bouton est celui de validation du formulaire, espace quand on avait le focus dessus avant de le désactiver, ou même le raccourci clavier qu'on a collé sur le bouton...

    J'ai même tenté de changer le Enable alors que le bouton de la souris était déjà enfoncé... Géré les événements MouseClick, KeyPress, DoubleClick... Quand c'est disable, c'est disable, aucun événement ne se déclenche...
    On ne jouit bien que de ce qu’on partage.

  4. #4
    Expert éminent sénior
    Peut être dans le cas d’un traitement long avec reclic pendant le traitement
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Expert éminent
    Citation Envoyé par Pol63 Voir le message
    Peut être dans le cas d’un traitement long avec reclic pendant le traitement
    Ah oui, mais alors dans le cas d'un tel traitement, il faut toujours penser à disable le bouton dans la première ligne du click.
    En effet, si on le disable en fin de traitement, on peut recliquer autant de fois qu'on veut tant que le traitement n'est pas terminé... et c'est la fête du slip, on commande des consoles gratos sur Grosbill et tout ça... (ancien bug corrigé depuis très longtemps )

    -- Edit : bah mince, même dans ce cas, marche pas.

    Code csharp :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
            private void ToggleColor()
            {
                for (int i = 0; i < 500000; i++) { pictureBox1.BackColor = i % 2 == 0 ? Color.Yellow: Color.Orange ; } /* dure environ 0,5 seconde */
                Thread.Sleep(1000); /* dure environ 1 seconde */
                clicked = !clicked;
                pictureBox1.BackColor = clicked ? Color.Green : Color.Red;
                listBox1.Items.Add("Click!");
                button1.Enabled = false;
            }


    => J'ai beau cliquer comme un âne, ça ne se déclenche qu'une seule fois (contrôlable au contenu du ListBox) avant que le bouton ne soit désactivé...
    Ceci dit, là c'est presque pas normal. Je ne sais pas si ça a toujours bien fonctionné. Je teste avec le Framework 4.8

    Ou alors le traitement est dans un second thread ? Mais dans ce cas, oui, il ne faut surtout pas désactiver le bouton dans le traitement (même pas au début) mais directement dans la première ligne du handler, sinon rien que le temps de démarrer le second thread on peut avoir le temps de cliquer une seconde fois.
    On ne jouit bien que de ce qu’on partage.

  6. #6
    Expert éminent sénior
    Après je me suis pas posé sur autant de questions. A question étrange je mets une réponse étrange (recommander doevents c’est aller loin déjà ^^)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  7. #7
    Expert éminent sénior
    Citation Envoyé par StringBuilder Voir le message
    Ah oui, mais alors dans le cas d'un tel traitement, il faut toujours penser à disable le bouton dans la première ligne du click.
    En effet, si on le disable en fin de traitement, on peut recliquer autant de fois qu'on veut tant que le traitement n'est pas terminé... et c'est la fête du slip, on commande des consoles gratos sur Grosbill et tout ça... (ancien bug corrigé depuis très longtemps )
    Pour du winform, c'est uniquement valable si le traitement long est asynchrone (via async/await ou un thread dédié par exemple). Dans le cas contraire, le traitement bloque l'interface utilisateur (interface gelé) et les clics ultérieurs seront traités après le traitement, qui aura désactivé le bouton, donc événement ignoré.

    Normalement, mettre la propriété Enabled à false est suffisant pour bloquer un bouton. Si cela ne marche pas, il nous faudrait voir le code pour comprendre ce qui se passe.
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  8. #8
    Membre à l'essai
    Voici le code :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    private void buttonWriteFast_Click (object sender, EventArgs e)
    {
      buttonWriteFast.Enabled = false;
      WriteFast();
      buttonWriteFast.Enabled = true;
    }


    sachant que WriteFast() est un traitement qui dure 5 minutes.

    Le bouton est bien grisé, mais quand je clique dessus, le traitement se relancera après la fin du 1er traitement, ce qui prouve que le bouton est toujours actif.

    Comment résoudre ce problème ?

    Merci.

  9. #9
    Expert éminent sénior
    Le comportement est donc totalement normal. Ton UI est en réalité gelé par le traitement long. Tu désactives le bouton, tu fais le traitement, puis tu le réactives. Ce qu'il faut comprendre c'est que tant que tu es dans ta méthode buttonWriteFast_Click, aucun message n'est traité. Donc quand tu cliques sur ton bouton, les messages sont mis en attente. Une fois la méthode terminée, les messages en attente sont traités. S'il y a des clics sur le bouton, le bouton est donc recliqué car l'état du bouton à ce moment précis sera un état actif.

    Une manière de ne pas avoir le problème, est de réécrire légèrement le code :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    private async void buttonWriteFast_Click (object sender, EventArgs e)
    {
      buttonWriteFast.Enabled = false;
      await Task.Run(() =>  WriteFast());
      buttonWriteFast.Enabled = true;
    }


    Ainsi, le traitement long sera exécuté sur un thread à part, et ne bloquera pas le thread principal, ce qui permettra aux messages d'événement d'être traité comme il se doit (ici, clic sur bouton ignoré car traité quand le bouton est désactivé).
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  10. #10
    Membre à l'essai
    Merci !
    Je me demandais si c'était aussi possible d'arrêter la fonction en cliquant sur un bouton stop par exemple sous C#. Ce n'est peut-être pas le sujet de ce fil, alors j'ai ouvert une autre discussion. Si tu pouvais regarder, je te remercie.

###raw>template_hook.ano_emploi###