检查TreeView控件节点和子节点 - StackOverflowException!

时间:2010-10-19 19:26:23

标签: c# winforms visual-studio-2008

我有一个使用CheckBoxes属性的Windows应用程序的树视图控件。

有时(通常)在选中或取消选中Tree Node时,我会在下面的静态方法中获得Stack Overflow Exceptions。

有人能指出原因吗?也许甚至告诉我如何以正确的方式做到这一点?

在After Check Event中,我写了以下内容:

void TreeNode_AfterCheck(object sender, TreeViewEventArgs e) {
  if (0 < e.Node.Nodes.Count) {
    if (e.Node.Checked) {
      e.Node.Expand();
      TreeNodes_SetChecksTo(e.Node, true);
    } else {
      if (!TreeNode_SomethingChecked(e.Node)) {
        e.Node.Collapse(false);
      }
    }
  }
}

通常,当静态方法中的某些内容触发上面的After Check事件并进入下面的一个静态方法时,抛出异常:

static void TreeNodes_SetChecksTo(TreeNode node, bool value) {
  if (node != null) {
    if (node.Checked != value) node.Checked = value;
    if (0 < node.Nodes.Count) {
      foreach (TreeNode sub in node.Nodes) {
        TreeNodes_SetChecksTo(sub, value);
      }
    }
  }
}

static bool TreeNode_SomethingChecked(TreeNode node) {
  if (node != null) {
    if (node.Checked) return true;
    if (0 < node.Nodes.Count) {
      foreach (TreeNode sub in node.Nodes) {
        if (TreeNode_SomethingChecked(sub)) {
          return true;
        }
      }
    }
  }
  return false;
}

3 个答案:

答案 0 :(得分:2)

IsChecked内设置TreeNodes_SetChecksTo会导致AfterCheck事件被提升,从而调用TreeNode_AfterCheck方法。我怀疑你想在处理事件时禁用/忽略该事件:

private bool latch;

void TreeNode_AfterCheck(object sender, TreeViewEventArgs e) {
  if (latch)
      return;

  latch = true;

  try
  {
      if (0 < e.Node.Nodes.Count) {
        if (e.Node.Checked) {
          e.Node.Expand();
          TreeNodes_SetChecksTo(e.Node, true);
        } else {
          if (!TreeNode_SomethingChecked(e.Node)) {
            e.Node.Collapse(false);
          }
        }
      }
  }
  finally
  {
      latch = false;
  }
}

答案 1 :(得分:2)

if (node.Checked != value) node.Checked = value;

这是可能导致它的陈述。它会触发AfterCheck事件。当事件处理程序已经运行时,它将再次被调用。你需要保护自己免受攻击,并打破私人领域的递归。像这样:

private bool updatingChecks;

void TreeNode_AfterCheck(object sender, TreeViewEventArgs e) {
  if (updatingChecks) return;
  updatingChecks = true;
  try {
    // etc..
  }
  finally {
    updatingChecks = false;
  }
}

答案 2 :(得分:0)

每次(子)节点被检查或取消选中时,树都会递归迭代,这种情况经常发生,因为您对AfterCheck回调的每个检查状态更改做出反应。要么“禁止”回调,而它的“实例”已在处理,要么在没有显式递归的情况下执行回调,并让回调隐式执行递归。