1

Tree View 控件的 AfterCheck 事件会检查其下方的所有子节点,如果选中某些内容,则启用“运行”按钮。

1346 void TreeNode_AfterCheck(object sender, TreeViewEventArgs e) {
1347   if (!e.Node.Checked) return;
1348   foreach (TreeNode sub in e.Node.Nodes) {
1349     sub.Checked = e.Node.Checked;
1350   }
1351   RunButton.Enabled = IsANodeChecked();
1352 }

1429 static bool IsANodeChecked(TreeNode node) {
1430   if (node.Checked) return true;
1431   foreach (TreeNode sub in node.Nodes) {
1432     if (IsANodeChecked(sub)) {
1433       return true;
1434     }
1435   }
1436   return false;
1437 }

当有 4881 个子节点时检查根节点会挂掉 GUI 大约 7 秒。

我只需要调用一次 IsANodeChecked(在第 1351 行),但在处理完所有树节点之前我不知道如何禁用它。

而且我不想在我的表单上设置一个专门用于监控的计时器。

有没有人看到一个简单/明显的解决方案?

4

3 回答 3

2

在您的复选框上放置一个事件处理程序,以启用或禁用 RunButton,而不是让某些东西遍历整个事情以找出答案。

在第一次选中复选框时将复选框添加到选中的复选框列表中,这样您就不会禁用 RunButton,直到选中的复选框列表为空。未选中时将其从列表中删除等。

这是我写出来的一种方式,如果我错过了什么,这只是很抱歉:

private int _checkedCheckboxes;

void AddCheckBox()
{
    if (_checkedCheckBoxes++ == 1) RunButton.Enabled = true;
}

void RemoveCheckBox()
{
    if (_checkedCheckBoxes-- == 0) RunButton.Enabled = false;
}

void TreeNode_AfterCheck(object sender, TreeViewEventArgs e) 
{
    if (e.Node.Checked)
    {
        AddCheckBox();
        return;
    }

    RemoveCheckBox();
}
于 2010-08-20T19:34:56.330 回答
1

我有时使用 aTimer来处理这种情况。添加一个计时器并设置Tick事件处理程序以调用IsANodeChecked和启用/禁用按钮。给它一个短的时间间隔(可能约为 100 毫秒),然后将其禁用。然后,您调用事件处理程序StopStart的计时器,然后调用。AfterCheck这将导致每次调用 时重新启动计时器AfterCheck,但Tick事件处理程序仅在调用后经过一定时间后才会Start调用,这意味着直到最后一次调用后才会调用它AfterCheck

100 毫秒对计算机来说是一个长的工作时间,但对用户来说似乎是即时的。

您可以在 Windows 资源管理器中看到类似的行为。如果您使用键盘在文件夹树中快速导航,则包含文件夹内容的右侧窗格将不会更新,除非您在树中的文件夹上停留片刻。

于 2010-08-20T19:33:34.727 回答
0

这些想法很有帮助,但我使用了一些不同的方法,通过添加一个布尔变量来工作:

bool _treeNodeFirst = false;

...和一个 Before Checked 事件,它临时修改控件上的背景颜色以用作启动事件链的控件的标志:

1273 void TreeNode_BeforeCheck(object sender, TreeViewCancelEventArgs e) {
1274   if (!_treeNodeFirst) {
1275     _treeNodeFirst = true;
1276     e.Node.BackColor = Color.Silver;
1277   }
1278 }

1346 void TreeNode_AfterCheck(object sender, TreeViewEventArgs e) {
1347   if (e.Node.Checked) {
1348     foreach (TreeNode sub in e.Node.Nodes) {
1349       sub.Checked = e.Node.Checked;
1350     }
1351   }
1352   if (e.Node.BackColor == Color.Silver) {
1353     e.Node.BackColor = Color.Empty;
1354     RunButton.Enabled = IsANodeChecked();
1355     _treeNodeFirst = false;
1356   }
1357 }

1429 static bool IsANodeChecked(TreeNode node) {
1430   if (node.Checked) return true;
1431   foreach (TreeNode sub in node.Nodes) {
1432     if (IsANodeChecked(sub)) {
1433       return true;
1434     }
1435   }
1436   return false;
1437 }

这似乎是最好的方法(我现在可以看到),以确保IsANodeChecked(TreeNode)只在一次选择一组节点时运行一次。

不过,我确实很喜欢 Jimmy Hoffa 使用计数的想法。我可能会将其添加到我的代码中。

谢谢大家!〜乔

于 2010-08-20T21:22:46.813 回答