.NET TreeView вызывает сбой приложения при попытке проверить родительский узел - PullRequest
1 голос
/ 22 мая 2010

У меня есть TreeView с флажками, и когда пользователь проверяет дочерний узел, я хочу пройти вверх по дереву и проверить каждого родителя. Однако по какой-то причине мое приложение взрывается, когда я прикасаюсь к родительскому узлу. Для узлов в моем дереве я расширил TreeNode, чтобы создавать свои собственные объекты с некоторыми данными, которые мне нужно хранить в них, но я по-прежнему называю их TreeNodes при проверке / снятии отметки. Мой код выглядит так:

//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);
    }
}

Ответы [ 3 ]

2 голосов
/ 22 мая 2010

Хорошо, разобрался. Это не была круговая ссылка, но она, безусловно, была круговой по своей природе. Это была большая глупая ошибка с моей стороны ... в обработчике событий я использовал рекурсию, чтобы также проверить ВНИЗ дерево ... Я реализовал это некоторое время назад и не задумывался об этом, поэтому, когда я добавил еще одну часть рекурсии для проверки дерева я закончил бесконечным циклом между функцией рекурсии и обработчиком события (который вызывался каждый раз, когда рекурсивная функция проверяла один из узлов .. событие After_checked). Ба.

0 голосов
/ 22 мая 2010

Если у вас действительно есть циклическая ссылка, то вы получите переполнение стека, которое невозможно отловить Попробуйте изменить код, чтобы избавиться от рекурсии:

// checkBox checked event handler
checkAllParents(node);

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

Если приложение входит в бесконечный цикл, у вас есть круговая ссылка. Вы можете дополнительно изменить код, чтобы перехватывать циклические ссылки:

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;
  }
}

Конечно, это не подходящее место для обработки циклических ссылок. Но если это поможет ..

0 голосов
/ 22 мая 2010

Это должна быть бесконечная рекурсия, которая уносит стек (переполнение стека не меньше). node.Parent никогда не должен иметь нулевое значение. Он не будет пойман при попытке try, потому что ваш код не вызывает исключение, вы просто вызываете переполнение стека, и это среда .net, которая генерирует исключение. Вы также будете запускать рекурсию несколько раз, каждый раз, когда вы устанавливаете node.Checked = true; Вы снова запустите обработчик событий, но вы также снова вызовите проверку всех родителей, я бы удалил рекурсивный вызов, чтобы проверить всех родителей, и просто установил узел в флажок, обработчик событий сделает рекурсию за вас.

...