如何从DataGridView加载List<T>?加载列数据遇空引用异常求解
解决DataGridView加载List时的NullReferenceException问题
先分析你遇到的空引用异常,大概率出自这几个场景:
- 目标单元格的
Value是null或者DBNull.Value,直接强制(string)转换会触发异常 - 遍历到了DataGridView默认的新增空白行(
Rows[i].IsNewRow为true),这一行的单元格值全为空 - 列索引
Cells[2]超出了实际列数,导致单元格对象本身就是null
给你修复后的LoadStringList方法,补上了空值校验和跳过新增行的逻辑:
public static List<string> LoadStringList() { List<string> stringList = new List<string>(); // 先确保DataGridView实例不为空 if (contactDataGridView == null || contactDataGridView.RowCount == 0) { return stringList; } // 遍历行时跳过新增空白行 foreach (DataGridViewRow row in contactDataGridView.Rows) { if (row.IsNewRow) continue; // 检查目标单元格是否存在 if (row.Cells.Count > 2 && row.Cells[2] != null) { // 统一处理DBNull和null的情况,转成空字符串或按需忽略 string cellValue = row.Cells[2].Value == DBNull.Value ? string.Empty : row.Cells[2].Value?.ToString(); // 可选:只添加非空非空白的内容 if (!string.IsNullOrWhiteSpace(cellValue)) { stringList.Add(cellValue); } } } return stringList; }
从DataGridView加载List的通用方法
下面提供两种实用的通用加载思路,适配不同场景:
1. 强类型实体手动映射(性能优、易维护)
如果你的目标是已知结构的实体类,比如Contact,可以手动绑定单元格值到实体属性:
// 示例实体类 public class Contact { public string Name { get; set; } public int Age { get; set; } public string Email { get; set; } } public static List<Contact> LoadContactList() { List<Contact> contacts = new List<Contact>(); if (contactDataGridView == null || contactDataGridView.RowCount == 0) { return contacts; } foreach (DataGridViewRow row in contactDataGridView.Rows) { if (row.IsNewRow) continue; Contact contact = new Contact(); // 按列索引/列名赋值,同时处理空值和类型转换 contact.Name = row.Cells["ColumnName_Name"].Value?.ToString() ?? string.Empty; contact.Age = int.TryParse(row.Cells["ColumnName_Age"].Value?.ToString(), out int age) ? age : 0; contact.Email = row.Cells[2].Value?.ToString() ?? string.Empty; contacts.Add(contact); } return contacts; } // 使用方式 List<Contact> contactList = LoadContactList();
2. 反射自动映射(灵活适配任意实体)
如果想适配任意实体类,不需要手动写映射逻辑,可以用反射根据列名和属性名自动匹配:
public static List<T> LoadGenericEntityList<T>(DataGridView dgv) where T : new() { List<T> entityList = new List<T>(); if (dgv == null || dgv.RowCount == 0) return entityList; Type entityType = typeof(T); var properties = entityType.GetProperties(); foreach (DataGridViewRow row in dgv.Rows) { if (row.IsNewRow) continue; T entity = new T(); foreach (var prop in properties) { // 找到与属性名匹配的列(忽略大小写) DataGridViewColumn targetCol = dgv.Columns.Cast<DataGridViewColumn>() .FirstOrDefault(col => string.Equals(col.Name, prop.Name, StringComparison.OrdinalIgnoreCase)); if (targetCol != null && row.Cells[targetCol.Index] != null) { object cellValue = row.Cells[targetCol.Index].Value; // 把DBNull转成null,统一处理空值 if (cellValue == DBNull.Value) cellValue = null; // 尝试转换类型并赋值,转换失败时设为默认值 try { object convertedValue = cellValue == null ? prop.PropertyType.IsValueType ? Activator.CreateInstance(prop.PropertyType) : null : Convert.ChangeType(cellValue, prop.PropertyType); prop.SetValue(entity, convertedValue); } catch { // 可选:记录转换失败日志 prop.SetValue(entity, null); } } } entityList.Add(entity); } return entityList; } // 使用方式 List<Contact> contactList = LoadGenericEntityList<Contact>(contactDataGridView);
额外注意事项
- 始终优先检查
DataGridView、DataGridViewRow、DataGridViewCell是否为null,从根源避免空引用 - 数据库空值在DataGridView中会以
DBNull.Value存在,不能直接转换为普通.NET类型,必须单独处理 - 记得跳过
IsNewRow:默认情况下DataGridView最后一行是用于新增的空白行,不需要加入结果列表
内容的提问来源于stack exchange,提问作者Andrey Kaplun
相关产品推荐
相关产品推荐

