2010-07-20 5 views
1

Mon projet est WinForms, C#.Cocher ou décocher tous les enfants TreeViewItem

J'ai un formulaire avec TreeView avec CheckBoxes défini sur true. Il y a quelques nœuds racines ayant chacun plusieurs nœuds enfants.

Je souhaite que tous les nœuds enfants aient le même état coché/non coché que leur parent. J'ai écrit le gestionnaire d'événement suivant:

private void treeView1_AfterCheck(object sender, TreeViewEventArgs e) 
{ 
    // return in case the event is induced by the code below 
    if (e.Action == TreeViewAction.Unknown) 
    { 
    return; 
    } 
    System.Diagnostics.Debug.WriteLine(string.Format("Checked - {0}", e.Node.Checked)); 
    foreach (TreeNode subNode in e.Node.Nodes) 
    { 
    subNode.Checked = e.Node.Checked; 
    } 
} 

Cependant, cela fonctionne assez étrange lorsque vous cliquez sur le parent rapidement. Je peux facilement le reproduire en cochant et décochant rapidement parent de sorte que les sous-noeuds sont tous vérifiés tandis que le parent est déjà décochée.

Comment faire cela plus correctement?

+0

Il semble que cet événement ne soit pas appelé lorsque vous cliquez rapidement. J'ai ajouté System.Diagnostics.Debug.WriteLine (string.Format ("Checked - {0}", e.Node.Checked)); à la première ligne et ne peut pas voir "Checked - false" pour la deuxième (décocher) cliquez. – Alex

+0

Je n'ai pu reproduire ce comportement que si j'ai neutralisé le comportement du double clic. Sinon, cliquer rapidement agrandit/contracte le nœud sur lequel vous cliquez. – msergeant

+0

msergeant, cliquez rapidement sur la case à cocher, pas sur le texte de l'article. il ne devrait pas se développer ou s'effondrer. – Alex

Répondre

3

Ceci est un bogue introduit par la version Vista du contrôle TreeView natif. Il répond à un double-clic en basculant automatiquement une case à cocher. Mais sans lever les événements BeforeCheck et AfterCheck. Le wrapper de classe Windows Forms TreeView n'a pas été mis à jour pour résoudre ce problème. La correction est assez simple, vous devez empêcher le contrôle natif de voir le double-clic. Ajoutez une nouvelle classe à votre projet et collez le code ci-dessous. Compiler. Déposez le nouveau contrôle du haut de la boîte à outils sur votre formulaire, en remplaçant l'arborescence existante.

using System; 
using System.Windows.Forms; 

public class MyTreeView : TreeView { 
    protected override void WndProc(ref Message m) { 
    // Suppress WM_LBUTTONDBLCLK 
    if (m.Msg == 0x203) { m.Result = IntPtr.Zero; } 
    else base.WndProc(ref m); 
    } 
} 
+0

Merci, Hans! Cela fonctionne parfaitement. Cependant, peut-être est-il sensé de remplacer le double-clic et envoyer l'événement AfterCheck manuellement? Que penses-tu? – Alex

+0

Votre programme ne fonctionnerait plus correctement sous XP. C'est possible, mais vous devrez lire l'état de vérification de l'élément après l'appel de base.WndProc. Le P/Invoke est difficile. –

1

Nous ajoutons une minuterie qui démarre/réinitialise lorsque vous cliquez. Si la minuterie se déclenche après 500ms, le code de mise à jour est exécuté.

Ceci corrigera le clic rapide l'un après l'autre.

+0

Merci - va essayer. Cependant cela m'étonne que le second événement ne soit jamais reçu par le contrôle! Cela semble être un bug de framework. – Alex

+0

Pouvez-vous s'il vous plaît partager le code? – Alex

0

Lorsque vous cliquez rapidement, l'événement de double clic se déclenche au lieu du simple clic. Le comportement du simple clic est ce qui change le statut vérifié. Si vous avez fait quelque chose pour contourner le comportement normal du double clic, assurez-vous d'en tenir compte sur les nœuds enfants.

+0

Non, je clique assez lentement pour ne pas recevoir l'événement double-clic. Je remplace cet événement pour m'assurer. – Alex

Questions connexes