C# DataGridView CellValueChanged事件e.RowIndex触发ArgumentOutOfRangeException异常
异常触发原因
- 核心触发点是
e.RowIndex值非法:CellValueChanged事件会在DataGridView底部的**新行占位符(待输入的空白新增行)**单元格内容变动时触发,此时e.RowIndex的返回值为-1,直接用该值访问Rows集合(索引从0开始)必然超出范围。 - 次要触发场景:事件触发时对应行已被删除、或数据源发生刷新导致行索引重置,此时
e.RowIndex大于等于当前Rows集合的总长度,也会触发索引越界。 - 你的代码还隐含其他潜在异常点:未判断单元格
Value为null的情况,直接调用ToString()会抛出空引用异常,同时字符串拼接SQL的写法存在SQL注入风险。
修复方案
- 事件入口首先添加索引合法性校验,不满足条件直接终止执行
- 增加单元格值非空判断,避免空引用异常
- 替换原有的字符串拼接SQL写法,改用参数化查询避免SQL注入风险
- 修正原代码中变量声明位置错误的语法问题,新增连接自动释放逻辑避免数据库连接泄漏
修正后代码
private void Sett_icts_DGV_prodAssign_CellValueChanged(object sender, DataGridViewCellEventArgs e) { // 校验行索引合法性,过滤新行占位符、已删除行的事件触发 if (e.RowIndex < 0 || e.RowIndex >= Sett_icts_DGV_prodAssign.Rows.Count) { return; } var currentRow = Sett_icts_DGV_prodAssign.Rows[e.RowIndex]; // 校验prodassignid单元格值非空 if (currentRow.Cells["prodassignid"].Value == null) { return; } string prodid = currentRow.Cells["prodassignid"].Value.ToString(); int prodid1 = string.IsNullOrEmpty(prodid) ? 0 : Convert.ToInt32(prodid); // 校验其他必填单元格值非空 if (currentRow.Cells["prodassigndesc"].Value == null || currentRow.Cells["prodassignkey"].Value == null) { return; } string prodassigndesc = currentRow.Cells["prodassigndesc"].Value.ToString(); int prodassignkey = Convert.ToInt32(currentRow.Cells["prodassignkey"].Value.ToString()); // 使用using自动释放数据库连接 using (var conn2 = new SqlConnection("替换为你的数据库连接字符串")) { conn2.Open(); if (prodid1 == 0) { // 参数化插入语句 string query601A = @"INSERT INTO ihsasprodassign(prodassigndesc, prodassignkey, prodassigndte, prodassigntme, prodassignstat) VALUES(@desc, @key, @dte, @tme, @stat)"; using (var cmda = new SqlCommand(query601A, conn2)) { cmda.Parameters.AddWithValue("@desc", prodassigndesc); cmda.Parameters.AddWithValue("@key", prodassignkey); cmda.Parameters.AddWithValue("@dte", DateTime.Now); cmda.Parameters.AddWithValue("@tme", DateTime.Now); cmda.Parameters.AddWithValue("@stat", "A"); cmda.ExecuteNonQuery(); } } else { // 参数化更新语句 string query601B = @"UPDATE ihsasprodassign set prodassigndesc=@desc, prodassignkey=@key, prodassignmod=@mod WHERE prodassignid=@id"; using (var cmda = new SqlCommand(query601B, conn2)) { cmda.Parameters.AddWithValue("@desc", prodassigndesc); cmda.Parameters.AddWithValue("@key", prodassignkey); cmda.Parameters.AddWithValue("@mod", DateTime.Now); cmda.Parameters.AddWithValue("@id", prodid1); cmda.ExecuteNonQuery(); } } } }
内容的提问来源于stack exchange,提问作者J.szareyo
相关产品推荐
相关产品推荐

