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行),但我不知道如何在处理完所有树节点之前禁用它。
我不希望在我的表格上有一个专门用来监控它的计时器。
有没有人看到一个简单/明显的解决方案?
答案 0 :(得分: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();
}
答案 1 :(得分:1)
我有时使用Timer
来处理此类案件。添加计时器并设置Tick
事件处理程序以调用IsANodeChecked
并启用/禁用该按钮。给它一个短暂的间隔(也许约100毫秒),并将其禁用。然后,在Stop
事件处理程序中的计时器上调用Start
,然后调用AfterCheck
。这将导致每次调用AfterCheck
时重新启动计时器,但只有在Tick
调用后经过一定时间后才会调用Start
事件处理程序,这意味着它在最后一次调用AfterCheck
之后才会调用。
100毫秒是计算机工作的非常长时间,但对于用户来说似乎是即时的。
您可以在Windows资源管理器中看到类似的行为。如果使用键盘在文件夹树中快速导航,则除非您短暂停留在树中的文件夹上,否则包含文件夹内容的右侧窗格将不会更新。
答案 2 :(得分:0)
这些想法很有用,但我使用了一些不同的东西,通过添加一个布尔变量来起作用:
bool _treeNodeFirst = false;
...还有一个Before Checked事件,它暂时修改控件上的Back Color,作为启动事件链的控件的标志:
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)
仅在一次选择一组节点时运行一次。
感谢大家! 〜乔