You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将CheckBoxList项设为只读或删除?WinForm开发技术求助

解决CheckBoxList绑定DataSource后无法修改项及DataGridView列只读/隐藏问题

先帮你梳理下核心问题:你遇到的Items collection cannot be modified when the DataSource property is set错误,是因为当CheckBoxList绑定了数据源后,它的Items集合是由数据源驱动的,不能直接增删操作——必须通过修改数据源本身来实现项的变更。另外你的需求分两种场景,我分别给你对应解决方案:

一、先修正现有代码的重复绑定问题

你当前的代码把checkedListBoxIPColumns.DataSource = columns;放在了遍历DataGridView列的循环里,这会导致多次重复绑定,完全没必要,先把这部分代码调整到循环外:

// 先一次性获取所有列的Name和HeaderText作为数据源
var columns = ((MainSoftwareForm)mainSoftware).dataGridViewImportParts.Columns
    .Cast<DataGridViewColumn>()
    .Select(x => new { x.Name, x.HeaderText })
    .ToList();

// 只做一次数据源绑定
checkedListBoxIPColumns.DataSource = columns;
checkedListBoxIPColumns.ValueMember = "Name";
checkedListBoxIPColumns.DisplayMember = "HeaderText";

// 初始勾选逻辑:根据数据库列的AllowDBNull设置选中状态
for (int i = 0; i < checkedListBoxIPColumns.Items.Count; i++)
{
    if (mOS_PackOSDataSet.PARTLIST.Columns[i].AllowDBNull == true)
    {
        checkedListBoxIPColumns.SetItemChecked(i, true);
    }
}

二、方案1:将未勾选的列设为只读(不需要修改CheckBoxList的项)

如果你的需求是保留所有列选项,但未勾选的列在DataGridView里设为只读,只需要修改ItemCheck事件的逻辑,把Visible换成ReadOnly即可:

checkedListBoxIPColumns.ItemCheck += (obj, args) =>
{
    dynamic item = checkedListBoxIPColumns.Items[args.Index];
    var isReadOnly = args.NewValue != CheckState.Checked; // 未勾选则设为只读
    ((MainSoftwareForm)mainSoftware).dataGridViewImportParts.Columns[(string)item.Name].ReadOnly = isReadOnly;
    // 如果你同时需要隐藏未勾选列,保留下面这行:
    // ((MainSoftwareForm)mainSoftware).dataGridViewImportParts.Columns[(string)item.Name].Visible = args.NewValue == CheckState.Checked;
};

三、方案2:删除CheckBoxList中未勾选的项(需修改数据源重新绑定)

如果一定要删除未勾选的项,因为不能直接操作Items集合,你需要:

  1. 从数据源列表中筛选出已勾选的项
  2. 重新绑定CheckBoxList的数据源

可以添加一个按钮(比如"确认删除未勾选项"),在按钮点击事件里处理:

private void btnRemoveUnchecked_Click(object sender, EventArgs e)
{
    // 获取当前已勾选的项
    var checkedItems = checkedListBoxIPColumns.CheckedItems
        .Cast<dynamic>()
        .Select(x => new { x.Name, x.HeaderText })
        .ToList();

    // 重新绑定数据源(先清空旧绑定避免报错)
    checkedListBoxIPColumns.DataSource = null;
    checkedListBoxIPColumns.DataSource = checkedItems;
    checkedListBoxIPColumns.ValueMember = "Name";
    checkedListBoxIPColumns.DisplayMember = "HeaderText";

    // 同步处理DataGridView中未勾选的列(隐藏或删除二选一)
    var allColumnNames = ((MainSoftwareForm)mainSoftware).dataGridViewImportParts.Columns
        .Cast<DataGridViewColumn>()
        .Select(x => x.Name);
    var uncheckedNames = allColumnNames.Except(checkedItems.Select(x => x.Name));
    
    foreach (var name in uncheckedNames)
    {
        // 选项1:隐藏列(可恢复)
        ((MainSoftwareForm)mainSoftware).dataGridViewImportParts.Columns[name].Visible = false;
        // 选项2:删除列(删除后无法恢复,需重新加载数据源)
        // ((MainSoftwareForm)mainSoftware).dataGridViewImportParts.Columns.Remove(name);
    }
}

额外提示

  • 不要在遍历DataGridView列的循环里重复绑定数据源,这会导致控件频繁刷新,影响性能和逻辑正确性
  • 如果你用的是匿名类型作为数据源,后续修改数据源时要保持结构一致;如果需要更灵活的操作,可以定义一个简单的类(比如ColumnInfo)来存储Name和HeaderText,比匿名类型更清晰

内容的提问来源于stack exchange,提问作者Ares

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:41:05