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

在datagridview批量更新时如何跳过未触发编辑的行?

方案1:无数据源绑定场景(自行维护编辑行集合,稳定性最高)

这种方式不管你有没有给DataGridView绑定数据源都可以用,不会受控件排序、刷新等操作的影响。

  1. 先在窗体类中定义一个全局的哈希集合,用来存储已编辑行的索引:
// 定义在窗体类内部,方法外
private HashSet<int> _editedRowIndexSet = new HashSet<int>();
  1. 给dgViewTask绑定CellEndEdit事件,只要用户完成单元格编辑就把行索引加入集合:
private void dgViewTask_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    // 排除表头行和空白新增行
    if (e.RowIndex >= 0 && !dgViewTask.Rows[e.RowIndex].IsNewRow)
    {
        _editedRowIndexSet.Add(e.RowIndex);
    }
}

如果你的业务允许用户删除行,建议同时绑定UserDeletingRow事件,避免后续遍历到已删除的行索引报错:

private void dgViewTask_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
{
    _editedRowIndexSet.Remove(e.Row.Index);
}
  1. 替换原来的全量遍历逻辑,只遍历已编辑的行:
int totalAffected = 0;
// 只遍历修改过的行
foreach (int rowIdx in _editedRowIndexSet)
{
    DataGridViewRow currentRow = frm1.dgViewTask.Rows[rowIdx];
    if (frm1.btnMLA.Enabled == false)
    {
        objNPTBEL.reportingDate = reportingDate.ToString();
        objNPTBEL.startDate = startDate.ToString();
        objNPTBEL.endDate = endDate.ToString();
    }
    else
    {
        objNPTBEL.reportingDate = reportingDate1.ToString();
        objNPTBEL.startDate = estStartDate.ToString();
        objNPTBEL.endDate = estEndDate.ToString();
    }
               
    objNPTBEL.id = Convert.ToInt32(currentRow.Cells[0].Value);
    objNPTBEL.taskname = currentRow.Cells[4].Value.ToString();
    objNPTBEL.remarks = currentRow.Cells[5].Value.ToString();

    int curRes = objNPTBLL.NonProcessingTime(9, objNPTBEL.id, objNPTBEL.workdayID, objNPTBEL.taskname, objNPTBEL.reportingDate, objNPTBEL.remarks, objNPTBEL.startDate, objNPTBEL.endDate, null, null, objNPTBEL.eststartDate, objNPTBEL.estendDate, null, objNPTBEL.estreportingDate, null, null, objNPTBEL.rationale);
    if(curRes > 0) totalAffected++;
}
// 保存完成后清空集合,下次编辑重新收集
_editedRowIndexSet.Clear();

if (totalAffected > 0)
{
    MessageBox.Show("更新成功", "DigiTrack", MessageBoxButtons.OK, MessageBoxIcon.Information);
    frm1.RefreshdgViewTask();
    frm1.clearVariable();
    this.Hide();
}

方案2:绑定了DataTable数据源场景(代码量最少)

如果你给DataGridView绑定的数据源是DataTable,直接用DataTable自带的行状态筛选即可,不需要额外监听事件:

DataTable sourceDt = (DataTable)frm1.dgViewTask.DataSource;
// 筛选出所有已修改的行
DataRow[] modifiedRows = sourceDt.Select("", "", DataViewRowState.ModifiedCurrent);

int totalAffected = 0;
foreach (DataRow dr in modifiedRows)
{
    // 直接从DataRow取字段值即可,不用读取控件单元格
    if (frm1.btnMLA.Enabled == false)
    {
        objNPTBEL.reportingDate = reportingDate.ToString();
        objNPTBEL.startDate = startDate.ToString();
        objNPTBEL.endDate = endDate.ToString();
    }
    else
    {
        objNPTBEL.reportingDate = reportingDate1.ToString();
        objNPTBEL.startDate = estStartDate.ToString();
        objNPTBEL.endDate = estEndDate.ToString();
    }
               
    objNPTBEL.id = Convert.ToInt32(dr[0]);
    objNPTBEL.taskname = dr[4].ToString();
    objNPTBEL.remarks = dr[5].ToString();

    int curRes = objNPTBLL.NonProcessingTime(9, objNPTBEL.id, objNPTBEL.workdayID, objNPTBEL.taskname, objNPTBEL.reportingDate, objNPTBEL.remarks, objNPTBEL.startDate, objNPTBEL.endDate, null, null, objNPTBEL.eststartDate, objNPTBEL.estendDate, null, objNPTBEL.estreportingDate, null, null, objNPTBEL.rationale);
    if(curRes > 0) totalAffected++;
}
// 重置行状态,下次修改会重新标记为Modified
sourceDt.AcceptChanges();

临时兼容方案

如果不想改动太多现有代码,可以直接在原有循环的最开头加一行判断,跳过未修改的行,不过这种方式的行状态可能会被控件排序、刷新等操作重置,适合临时使用:

for (int i = 0; i < frm1.dgViewTask.Rows.Count; i++)
{
    // 新增这一行,跳过未修改的行
    if (!frm1.dgViewTask.Rows[i].Modified) continue;
    // 原有逻辑不变
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 08:06:04