C# CheckListBox获取选中项ValueMember、DisplayMember及遍历选中项空引用问题求助
咱们先从最核心的问题说起——你的数据源设置方式不对,这直接导致了后面遍历、取值时的各种异常,咱们一步步来修正:
1. 先修正数据源的正确设置方式
你之前循环设置DisplayMember、ValueMember,还只把currencyName添加到Items里,这完全搞错了逻辑。DisplayMember和ValueMember是CheckListBox控件的全局属性,用来指定数据源中哪个属性负责显示、哪个作为值成员,不需要循环重复设置。而且必须把完整的Currency对象添加到Items中,而不是只加字符串,这样后面才能直接获取对象的属性值。
正确写法如下:
// 获取完整的数据源列表 var currencyList = db.currencies.ToList(); // 设置控件的显示/值成员(填的是Currency类的属性名,不是具体值) chklistCurrency.DisplayMember = nameof(Currency.currencyName); chklistCurrency.ValueMember = nameof(Currency.currencySymbol); // 直接添加整个对象数组(推荐) chklistCurrency.Items.AddRange(currencyList.ToArray()); // 或者用DataSource绑定更规范: // chklistCurrency.DataSource = currencyList;
这样设置后,CheckListBox会自动根据DisplayMember显示currencyName,每个Item对应的都是完整的Currency对象,后续操作就顺畅多了。
2. 遍历选中项并获取Value/Display值
你之前转DataRowView出现空引用,是因为你的数据源是List<Currency>,不是DataTable,所以CheckedItems里的每个项都是Currency对象,不是DataRowView。直接强转成Currency即可:
foreach (var itemChecked in chklistCurrency.CheckedItems) { // 强转成你的Currency实体类,同时做空值判断避免异常 var currencyItem = itemChecked as Currency; if (currencyItem == null) continue; // 直接访问实体类的属性,对应DisplayMember和ValueMember string displayName = currencyItem.currencyName; string symbol = currencyItem.currencySymbol; // 这里执行你的业务逻辑,比如创建CurrencyAccount var cra = new CurrencyAccount(); cra.CurrencyName = displayName; cra.CurrencySymbol = symbol; // ... }
3. 为什么itemChecked.ValueMember会标红报错?
ValueMember和DisplayMember是CheckListBox控件本身的属性,用来告诉控件如何解析数据源,不是每个Item的属性。所以你不能通过itemChecked.ValueMember获取值,而是有两种方式:
- 强转成实体类直接访问属性(最推荐,类型安全)
- 用控件的内置方法获取(适合不确定Item类型的场景):
// 获取Display值 string displayText = chklistCurrency.GetItemText(itemChecked); // 获取Value值(.NET Framework 4.7.2及以上版本支持) object value = chklistCurrency.GetItemValue(itemChecked);
总结
所有问题的根源都是数据源设置错误——没有绑定完整的实体对象,而是只添加了字符串。修正数据源后,遍历选中项、获取值的操作就变得简单且不易出错了。
内容的提问来源于stack exchange,提问作者Developer

