代码之家  ›  专栏  ›  技术社区  ›  jp2code

带复选框的慢速TreeNode[大量]

  •  1
  • jp2code  · 技术社区  · 14 年前

    树状视图控件的AfterCheck事件检查它下面的所有子节点,如果检查了某些内容,则启用Run按钮。

    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行)一次,但我不知道如何禁用它,直到处理完所有树节点。

    我不想在我的表格上有一个计时器专门用来监视这个。

    有人看到简单/明显的解决方案吗?

    3 回复  |  直到 14 年前
        1
  •  2
  •   Jimmy Hoffa    14 年前

    在您的复选框上放置一个事件处理程序,启用或禁用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();
    }
    
        2
  •  1
  •   Fredrik Mörk    14 年前

    Timer 处理此类案件。添加计时器并设置 Tick 要调用的事件处理程序 IsANodeChecked Stop 然后 Start AfterCheck 事件处理程序。这将导致每次调用的计时器重新启动 事后检查 ,但是 滴答声 事件处理程序将仅在事件发生后经过一定时间时调用 起点 事后检查 .

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

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

        3
  •  0
  •   jp2code    14 年前

    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)

    不过,我真的很喜欢吉米·霍法的计数法。我可能会把它添加到我的代码中。