多个ListBox列表框多选联动实现及栈溢出异常问题咨询
问题根因
你遇到的StackOverflow异常是事件递归触发导致的:
- 修改ListBox1的选中状态会触发
listBox_1_SelectedIndexChanged,方法内部会修改ListBox2、ListBox3的选中状态 - 修改ListBox2的选中状态又会触发
listBox_2_SelectedIndexChanged,方法内部又会反过来修改ListBox1的选中状态 - 二者无限循环调用,最终栈空间耗尽抛出异常
另外现有代码存在索引越界隐患:ListBox的索引从0开始,最大有效索引是Items.Count - 1,你写的count <= listBox_2.Items.Count会在count等于Items.Count时访问不存在的索引,导致下标越界异常。
解决方案
1. 增加全局锁标记避免递归
在窗体类中定义布尔变量,标记当前是否处于程序主动更新选中状态的过程中,是则跳过事件处理,避免循环触发:
// 窗体类成员变量 private bool _isSyncingSelection = false;
2. 抽取公共同步逻辑,避免重复代码
写一个公共方法,传入触发同步的源ListBox,统一同步另外两个ListBox的选中状态:
private void SyncListBoxSelection(ListBox sourceListBox) { // 已经处于同步过程中,直接返回避免递归 if (_isSyncingSelection) return; try { _isSyncingSelection = true; // 遍历源ListBox所有条目 for (int i = 0; i < sourceListBox.Items.Count; i++) { bool isSelected = sourceListBox.GetSelected(i); // 同步到ListBox1(下标有效才操作) if (i < listBox_1.Items.Count) listBox_1.SetSelected(i, isSelected); // 同步到ListBox2(下标有效才操作) if (i < listBox_2.Items.Count) listBox_2.SetSelected(i, isSelected); // 同步到ListBox3(下标有效才操作) if (i < listBox_3.Items.Count) listBox_3.SetSelected(i, isSelected); } } finally { // 无论是否出现异常都重置标记,避免后续功能失效 _isSyncingSelection = false; } }
3. 简化三个ListBox的事件处理逻辑
三个ListBox的SelectedIndexChanged事件直接调用公共方法即可,无需分别编写重复逻辑:
private void listBox_1_SelectedIndexChanged(object sender, EventArgs e) { SyncListBoxSelection(listBox_1); } private void listBox_2_SelectedIndexChanged(object sender, EventArgs e) { SyncListBoxSelection(listBox_2); } private void listBox_3_SelectedIndexChanged(object sender, EventArgs e) { SyncListBoxSelection(listBox_3); }
内容的提问来源于stack exchange,提问作者JNL
相关产品推荐
相关产品推荐

