DataGridView插入复选框列时出现“列已归属控件”错误如何解决
异常根因
你定义的checkboxselect是类级别的全局列对象,并非KeyDown方法内部每次新建的局部实例。第一次触发查询时,这个列被正常插入dgvSampleDetails的列集合,归属到当前控件;第二次触发查询时,代码没有做前置校验就再次执行Insert方法,试图把同一个已经属于该控件的列对象重复加入集合,框架校验不通过就抛出了对应异常。
- 注意:即使你多次更换
DataSource、清空行数据,已经被添加到控件列集合里的自定义列也不会自动消失,依然保持对该控件的归属状态。
可行解决方案
方案1:插入前做存在性校验(最小改动,推荐)
直接在Insert逻辑前增加判断,跳过重复插入步骤,复用已有的复选框列实例,不会因为反复重建列导致行选中状态丢失。
调整后的事件代码:
private void txtOrder_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { dgvOrderDetails.DataSource = sample.SearchOrders1(txtOrder.Text); dgvSampleDetails.DataSource = sample.GetOrderSamples(txtOrder.Text); btnSave.Enabled = true; // 仅当复选框列未被添加时才执行插入、配置逻辑 if (!dgvSampleDetails.Columns.Contains(checkboxselect)) { dgvSampleDetails.Columns.Insert(0, checkboxselect); checkboxselect.HeaderText = "Select"; checkboxselect.Name = "select"; } } }
- 小提醒:不要为了避免报错每次在方法里new一个新的复选框列对象,这样反而会因为列名重复、列样式反复重置带来其他问题,复用同一个全局列实例的性能和稳定性都是最好的。
方案2:插入前显式移除已有实例
如果需要每次刷新数据时重新排布列的位置,可以在Insert前先把已存在的同名列从集合中移除,彻底解除旧实例和控件的归属关系:
// 先移除已存在的同名列 if (dgvSampleDetails.Columns.Contains("select")) { dgvSampleDetails.Columns.RemoveAt(0); } dgvSampleDetails.Columns.Insert(0, checkboxselect); checkboxselect.HeaderText = "Select"; checkboxselect.Name = "select";
注意:不建议直接打开之前注释掉的
dgvSampleDetails.Columns.Clear()逻辑,这种方式会清空所有自定义列配置,每次绑定数据源时都要重新生成全部业务列,既影响性能,也可能导致手动配置的列格式丢失。
方案3:把列初始化和查询逻辑彻底分开(最省心的长期方案)
不要把自定义列的插入、配置逻辑写在查询触发的KeyDown事件里,而是在窗体Load事件中一次性完成所有列的初始化配置,后续查询操作只需要刷新DataSource即可,全程不需要动态操作列集合,从根源上避免重复加列的问题。
内容的提问来源于stack exchange,提问作者Ziad Adnan
相关产品推荐
相关产品推荐

