我遇到了一个问题,我想在checkListBox中显示一个项目列表,并在我监控的每个进程完成后逐个编程检查它们。
我会尝试将我的代码简化为最基本的功能,这样每个人都可以轻松掌握正在发生的事情。
for (int i = 0; i < 10; i++)
{
SOME_FUNCTION();
progressBar.Value++;
checkListBoxItems.SetItemCheckState(i, CheckState.Checked);
}
这基本上就是我的代码所做的事情。循环运行时进度条会更新,但在循环结束并且同时检查它们之前,不会检查所有复选框。
这显然违背了显示复选框的目的,我很好奇是否有我遗漏的东西,允许你刷新checkListBox控件,或类似的东西。
如果这个问题看起来很模糊,我很抱歉,我似乎经常在这里遇到这个问题。
答案 0 :(得分:2)
这是任何Windows GUI应用程序的标准行为,在UI线程空闲之前不会发生屏幕更新,因此Windows可以提供Paint事件。你可以做的绝对最糟糕的事情之一就是调用Application.DoEvents()。是的,这将提供Paint事件。但它也允许您的用户关闭表单。当您尝试更新的控件突然不再存在时,会产生一个Big Kaboom。你的循环仍然在运行,但表单已经不存在了。
您必须注意的是进度条实际更新但CheckedListBox没有。这是因为当代码处于循环中时,ProgressBar通常用于显示进度,因此它确保当您更改Value属性时,它会立即自行绘制,而无需等待Windows告知它需要重新绘制。肮脏的把戏,非常令人困惑。
但你也可以利用这个技巧,这很容易。像这样修改你的代码:
for (int i = 0; i < 10; i++)
{
SOME_FUNCTION();
progressBar.Value++;
checkListBoxItems.SetItemCheckState(i, CheckState.Checked);
checkListBoxItems.Update();
}
Update()方法意味着“必要时自己画画”。是的,你改变了一个项目的检查状态。 Big Kaboom从未对你产生任何影响,用户不能突然让控件消失。
如果SOME_FUNCTION()需要很长时间,比如超过10 x 0.3秒左右,那么你应该开始考虑使用线程了。
答案 1 :(得分:0)
您可以在需要重新绘制的控件上调用Invalidate()
。
每次更新列表中的复选标记时都是这样的:
checkListBoxItems.Invalidate();
享受!
答案 2 :(得分:0)
for (int i = 0; i < 10; i++)
{
SOME_FUNCTION();
progressBar.Value++;
checkListBoxItems.SetItemCheckState(i, CheckState.Checked);
Application.DoEvents();
}