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

如何在DataGridView更新时仅将修改内容写入历史操作日志?

实现方案

你可以通过判断行的修改状态过滤需要记录日志的内容,以下是两种常用的实现方式:

方式1:绑定数据源场景(推荐,最省事)

如果你的DataGridView是绑定到DataTable作为数据源的,直接用DataRow自带的RowState属性判断即可,只有状态为DataRowState.Modified的行才是被修改过的:

using (MySqlConnection conn = new MySqlConnection("Data Source=" + clsSQLcon.sqlServerName + ";port=" + clsSQLcon.sqlPort + ";Initial Catalog =" + clsSQLcon.sqlDatabaseName + ";user id =" + clsSQLcon.sqlUserName + ";password=" + clsSQLcon.sqlPassword + ""))
{
    conn.Open();
    string query = "INSERT INTO tblhistorylogs(DATE_UPDATED,NAME,LOGS) VALUES(@Date,@Name,@HistoryLogs)";
    MySqlCommand command = new MySqlCommand(query, conn);

    // 先获取绑定的DataTable
    DataTable dt = (DataTable)dataGridView1.DataSource;
    // 先判断有没有修改过的行,避免空引用报错
    var modifiedRows = dt.GetChanges(DataRowState.Modified);
    if (modifiedRows != null)
    {
        foreach (DataRow row in modifiedRows.Rows)
        {
            if (txtPRSSearch.Text.Length <= 3)
                continue;
            
            command.Parameters.AddWithValue("@Date", DateTime.Today.ToString("yyyy-MM-dd"));
            command.Parameters.AddWithValue("@Name", "Updated by: " + LoginForm.SetValueForText1 +"\n("+ cbxPRSctrl.Text + "-" + txtPRSSearch.Text +")");
            command.Parameters.AddWithValue("@HistoryLogs",
              "STATUS: " + Convert.ToString(row[0]) + "\n" +
              "ITEM NAME: " + Convert.ToString(row[5]) + "\n" +
              "DATE RECEIVED: " + Convert.ToString(dataGridView2.Rows[dt.Rows.IndexOf(row)].Cells[0].Value) + "\n" +
              "RECEIVED BY: " + Convert.ToString(dataGridView3.Rows[dt.Rows.IndexOf(row)].Cells[0].Value) + "\n" +
              "SUPPLIER: " + Convert.ToString(dataGridView3.Rows[dt.Rows.IndexOf(row)].Cells[1].Value) + "\n" +
              "PO/PCF/PIS: " + Convert.ToString(dataGridView3.Rows[dt.Rows.IndexOf(row)].Cells[2].Value) + "\n" +
              "UNIT COST " + Convert.ToString(dataGridView3.Rows[dt.Rows.IndexOf(row)].Cells[3].Value) + "\n" +
              "AMOUNT: " + Convert.ToString(dataGridView3.Rows[dt.Rows.IndexOf(row)].Cells[4].Value) + "\n" +
              "REF/CV/JV: " + Convert.ToString(dataGridView3.Rows[dt.Rows.IndexOf(row)].Cells[5].Value) + "\n" +
              "DATEPAID: " + Convert.ToString(dataGridView3.Rows[dt.Rows.IndexOf(row)].Cells[6].Value) + "\n" +
              "INCHARGE: " + Convert.ToString(dataGridView3.Rows[dt.Rows.IndexOf(row)].Cells[7].Value) + "\n" +
              "TARGET DATE: " + Convert.ToString(dataGridView3.Rows[dt.Rows.IndexOf(row)].Cells[8].Value));

            command.ExecuteNonQuery();
            command.Parameters.Clear();
        }
    }
    // 操作完重置行状态
    dt.AcceptChanges();
}

方式2:未绑定数据源场景

如果是手动填充的DataGridView,你可以给每一行的Tag属性加标记,在CellEndEdit事件触发时把当前行的Tag设为true代表已修改:
首先添加单元格编辑结束事件:

private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    // 过滤空行,标记当前行已修改
    if (!dataGridView1.Rows[e.RowIndex].IsNewRow)
    {
        dataGridView1.Rows[e.RowIndex].Tag = true;
    }
}

然后在你的保存日志代码里加判断,只有Tag为true的行才记录:

using (MySqlConnection conn = new MySqlConnection("Data Source=" + clsSQLcon.sqlServerName + ";port=" + clsSQLcon.sqlPort + ";Initial Catalog =" + clsSQLcon.sqlDatabaseName + ";user id =" + clsSQLcon.sqlUserName + ";password=" + clsSQLcon.sqlPassword + ""))
{
    conn.Open();
    string query = "INSERT INTO tblhistorylogs(DATE_UPDATED,NAME,LOGS) VALUES(@Date,@Name,@HistoryLogs)";
    MySqlCommand command = new MySqlCommand(query, conn);

    for (int i = 0; i < dataGridView1.Rows.Count; i++)
    {
        // 过滤空行、未修改的行
        if (txtPRSSearch.Text.Length <= 3 || dataGridView1.Rows[i].IsNewRow || dataGridView1.Rows[i].Tag == null || !(bool)dataGridView1.Rows[i].Tag)
            continue;
        
        command.Parameters.AddWithValue("@Date", DateTime.Today.ToString("yyyy-MM-dd"));
        command.Parameters.AddWithValue("@Name", "Updated by: " + LoginForm.SetValueForText1 +"\n("+ cbxPRSctrl.Text + "-" + txtPRSSearch.Text +")");
        command.Parameters.AddWithValue("@HistoryLogs",
          "STATUS: " + Convert.ToString(dataGridView1.Rows[i].Cells[0].Value) + "\n" +
          "ITEM NAME: " + Convert.ToString(dataGridView1.Rows[i].Cells[5].Value) + "\n" +
          "DATE RECEIVED: " + Convert.ToString(dataGridView2.Rows[i].Cells[0].Value) + "\n" +
          "RECEIVED BY: " + Convert.ToString(dataGridView3.Rows[i].Cells[0].Value) + "\n" +
          "SUPPLIER: " + Convert.ToString(dataGridView3.Rows[i].Cells[1].Value) + "\n" +
          "PO/PCF/PIS: " + Convert.ToString(dataGridView3.Rows[i].Cells[2].Value) + "\n" +
          "UNIT COST " + Convert.ToString(dataGridView3.Rows[i].Cells[3].Value) + "\n" +
          "AMOUNT: " + Convert.ToString(dataGridView3.Rows[i].Cells[4].Value) + "\n" +
          "REF/CV/JV: " + Convert.ToString(dataGridView3.Rows[i].Cells[5].Value) + "\n" +
          "DATEPAID: " + Convert.ToString(dataGridView3.Rows[i].Cells[6].Value) + "\n" +
          "INCHARGE: " + Convert.ToString(dataGridView3.Rows[i].Cells[7].Value) + "\n" +
          "TARGET DATE: " + Convert.ToString(dataGridView3.Rows[i].Cells[8].Value));

        command.ExecuteNonQuery();
        command.Parameters.Clear();
        // 记录完重置修改标记
        dataGridView1.Rows[i].Tag = null;
    }
}

额外优化说明

如果需要记录具体修改的字段内容,可以在数据加载时给每行存储一份原始值副本,编辑后对比差异,只把修改的字段写入日志即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 10:54:04