2010-05-21 6 views
1

J'ai une TreeView avec des cases à cocher, et quand un utilisateur vérifie un noeud enfant, je veux monter l'arbre et vérifier chaque parent. Cependant, pour une raison quelconque, mon application explose chaque fois que je touche le nœud parent. Pour les noeuds dans mon arbre, j'ai étendu TreeNode pour créer mes propres objets avec certaines données que je dois stocker en eux, mais je les référence toujours comme TreeNodes lors de la vérification/décocher. Mon code ressemble à ceci:.NET TreeView provoque le blocage de l'application lors de la tentative de vérification Noeud parent

//checkBox checked event handler 
    if (node.Parent != null) 
    { 
     checkAllParents(node.Parent); 
    } 
// 

private void checkAllParents(TreeNode node) 
{ 
    node.Checked = true; 
    if (node.Parent != null) 
    { 
     checkAllParents(node.Parent); 
    } 
} 
+0

que diriez-vous du texte d'exception? –

+2

Il n'existe pas de TreeView C#. Quel est le nom complet de la classe TreeView dont vous parlez? –

+1

imprimer quelques informations de trace. Vous pouvez avoir une référence circulaire quelque part. –

Répondre

2

Ok, compris. Ce n'était pas une référence circulaire mais c'était très certainement de nature circulaire. C'était une grosse erreur stupide de ma part ... dans le gestionnaire d'événements j'utilisais la récursivité pour vérifier l'arbre aussi ... J'ai implémenté cela il y a un moment et je n'y ai pas vraiment pensé, alors quand j'ai ajouté un autre morceau de récursion pour vérifier l'arbre Je me suis retrouvé avec une boucle infinie entre la fonction de récurrence et le gestionnaire d'événements (qui était appelé chaque fois que la fonction récursive vérifiait l'un des noeuds ... l'événement After_checked). Bah.

+2

Vous avez donc fait déborder votre pile sur StackOverflow? –

+0

Naturellement =) Oh et ma solution était de supprimer le gestionnaire d'événements quand je suis entré dans la fonction de gestionnaire, d'effectuer la récursion, puis d'ajouter le gestionnaire d'événements à la fin de la fonction gestionnaire. Fonctionne parfaitement maintenant. – alexD

+1

+1 pour avoir posté votre réponse. Je vous suggère de cliquer sur la case à cocher pour l'accepter comme réponse. –

0

Ce doit être une récursion infinie qui souffle la pile (un débordement de pile pas moins). node.Parent ne doit jamais être évalué à null. Il ne sera pas pris dans une tentative d'essai parce que votre code ne lance pas d'exception, vous causez juste un débordement de pile et c'est le framework .net qui lance l'exception. Vous allez également déclencher la récursivité plusieurs fois, chaque fois que vous définissez node.Checked = true; vous allez à nouveau déclencher le gestionnaire d'événements, mais vous appelez également vérifier tous les parents à nouveau, je voudrais supprimer l'appel récursif pour vérifier tous les parents et juste définir le nœud à cocher, le gestionnaire d'événements fera la récursivité pour vous.

+0

J'ai retiré la récursivité et je l'ai juste fait faire le premier nœud Parent et il se bloque toujours. – alexD

+2

Étape par étape avec un débogueur, combien de fois est-il appelé? est-ce qu'il plante au premier appel? Quelle est la trace de la pile? –

0

Si vous avez vraiment une référence circulaire, vous obtiendrez un débordement de pile qui ne peut pas être détecté. Essayez de modifier votre code pour se débarrasser de la récursion:

// checkBox checked event handler 
checkAllParents(node); 

private void checkAllParents(TreeNode node) 
{ 
    var parent = node.Parent; 
    while (parent != null) { 
    { 
    parent.Checked = true; 
    parent = parent.Parent; 
    } 
} 

Si l'application entre dans une boucle infinie, alors vous avez une référence circulaire. Vous pouvez modifier davantage le code pour intercepter les références circulaires:

private void checkAllParents(TreeNode node) 
{ 
    var parent = node.Parent; 
    var visitedNodes = new List<TreeNode>(); 
    while (parent != null) 
    { 
    if (visitedNodes.Contains(parent)) 
     throw new InvalidOperationException("Circular reference!"); 
    visitedNodes.Add(parent); 
    parent.Checked = true; 
    parent = parent.Parent; 
    } 
} 

Bien sûr, ce n'est pas le bon endroit pour gérer des références circulaires. Mais si cela aide ..

Questions connexes