【发布时间】:2019-05-14 14:21:55
【问题描述】:
我在我的 C# 软件中使用 CheckedListBox。该软件通过图形界面检查和取消选中项目以及用户。我添加了一个按钮来取消选中所有项目。当用户按下按钮时,软件应取消选中所有项目。有时,当我在单击按钮后通过软件取消选中项目时,某些项目仍然出现在列表框的选中项目属性中。 CheckedListBox 是否可能需要一些时间来更新 CheckedItems 属性?还是我的 Invoke-Usage 有问题?
我发现,当我在取消选中和读取选中项之间设置断点时,选中的项会正确更新。
//---------------------------------------------
// function to get the checked items
//---------------------------------------------
public List<object> getCheckedItems() {
var returnedItems = new List<object>();
var checkedItems = checkedListBox.CheckedItems;
var iterator = checkedItems.GetEnumerator();
while ( iterator.MoveNext() )
returnedItems.Add( iterator.Current );
return returnedItems;
}
//---------------------------------------------
// function to uncheck an item
//---------------------------------------------
public void uncheckItem( object item ) {
if ( containsItem( item ) ) {
int index = checkedListBox.Items.IndexOf( item );
if ( checkedListBox.InvokeRequired ) {
var uncheckInvoker =
new MethodInvoker( () => checkedListBox.SetItemChecked( index, false ) );
checkedListBox.BeginInvoke( uncheckInvoker );
}
else
checkedListBox.SetItemChecked( index, false );
// the following two line are added for debugging
var items = checkedListBox.CheckedItems; // breakpoint here
Console.WriteLine( "number of checked items = " + items.Count );
}
else
throw new ArgumentException( "Item " + item + " is not available" );
}
//---------------------------------------------
//client code
//---------------------------------------------
var checkedItems = subTestListBox.getCheckedItems();
foreach ( var checkedItem in checkedItems )
subTestListBox.uncheckItem( checkedItem );
我希望在我调用 SetItemChecked( int, bool ) 函数后,checkedItems 属性会立即更新。
【问题讨论】:
-
如果您在此处放置断点,
BeginInvoke是否会被命中(您的代码是否包含多个线程)?此外,BeginInvoke不会等待调用完成,如果您想等待 listitem 在运行下一条语句之前实际取消选中,请使用Invoke。 -
@Fixation 是的,我的代码确实包含多个线程并且它得到了它。似乎使用
Invoke而不是BeginInvoke解决了这个问题。我会在完全测试后立即提供答案并标记它。谢谢 -
由于您不需要检查检查状态(因为您正在检查/取消检查所有这些),您可能还会通过一个简单的 for 循环来切换所有项目的状态而不是获得更好的性能使用枚举器查询。此外,一个检查是否需要调用而不是检查每个项目的函数会加快速度。
-
或者循环
CheckedIndices集合并将对应的Item索引设置为未选中:foreach (int i in checkedListBox.CheckedIndices) { checkedListBox.SetItemChecked(i, false); }。你的程序太复杂了。您还可以BeginInvoke一个委托方法,它在 UI 线程中运行并完成所有工作。 -
它们确实会立即更新,但不能保证您确实可以看到。控件必须重新绘制自己,当 UI 线程忙于“其他软件”时,这可能需要一段时间。 BeginInvoke() 只会让情况变得更糟,它不是很快,并且当工作线程调用它时,您可以轻松地使用太多重绘的 UI 线程。使用线程的正确方法是只检索数据。完成后更新 UI,例如在 BackgroundWorker.RunWorkerCompleted 事件中。所以只有一次重绘。
标签: c# winforms checkedlistbox