如何在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
相关产品推荐
相关产品推荐

