Delphi VCL DBGrid:切换行/数据集时取消保存行变更
DBGrid 实现修改行点击其他行取消修改的方案
完全可以实现这个需求,核心思路是在用户编辑当前行时先保存原始数据,当焦点切换到其他行时,恢复原始值并取消编辑状态,以下是具体实现步骤(以Delphi环境为例,其他支持DBGrid的开发环境逻辑通用):
- 定义存储原始数据的变量:在窗体类中声明一个
TStringList或数组,用来临时保存当前编辑行的各列原始值。 - 捕获编辑开始事件:在DBGrid的
OnEdit事件中,遍历当前行的所有列,将每个字段的原始值存入变量(格式可以是「字段名=原始值」)。 - 捕获行切换事件:通过数据集的
BeforeScroll事件(或DBGrid的OnRowExit事件),判断当前是否处于编辑状态。如果是,遍历保存的原始数据,逐一恢复对应字段的值,再调用数据集的Cancel方法取消编辑。 - 补充确认逻辑:如果用户通过按钮等方式确认修改,清空存储原始数据的变量,避免后续误恢复。
示例代码
// 窗体类私有变量声明 private FOriginalRowValues: TStringList; // 初始化变量 procedure TMainForm.FormCreate(Sender: TObject); begin FOriginalRowValues := TStringList.Create; end; // 释放变量 procedure TMainForm.FormDestroy(Sender: TObject); begin FOriginalRowValues.Free; end; // 开始编辑时保存原始行数据 procedure TMainForm.DBGrid1Edit(Sender: TObject); var I: Integer; Field: TField; begin FOriginalRowValues.Clear; for I := 0 to DBGrid1.Columns.Count - 1 do begin Field := DBGrid1.Columns[I].Field; if Assigned(Field) then FOriginalRowValues.Add(Field.FieldName + '=' + Field.AsString); end; end; // 切换行时恢复原始数据并取消编辑 procedure TMainForm.ADODataSet1BeforeScroll(DataSet: TDataSet); var I: Integer; FieldName, RawValue: string; SplitPos: Integer; begin if DataSet.State in [dsEdit, dsInsert] then begin for I := 0 to FOriginalRowValues.Count - 1 do begin SplitPos := Pos('=', FOriginalRowValues[I]); FieldName := Copy(FOriginalRowValues[I], 1, SplitPos - 1); RawValue := Copy(FOriginalRowValues[I], SplitPos + 1, MaxInt); DataSet.FieldByName(FieldName).AsString := RawValue; end; DataSet.Cancel; end; end;
注意事项
- 不同开发环境的事件名称可能略有差异(比如部分环境用
OnLeave替代BeforeScroll),核心逻辑保持一致即可。 - 如果涉及插入新行,需要在事件中判断数据集状态(
dsInsert),避免无效的原始数据恢复操作。 - 确保使用的数据集组件支持
Cancel方法(如ADODataSet、ClientDataSet等均支持)。
内容的提问来源于stack exchange,提问作者andoryu
相关产品推荐
相关产品推荐

