Как восстановить последнее значение поля по коду? - PullRequest
0 голосов
/ 10 января 2019

В обработчике событий TField.OnValidate я должен попросить пользователя подтвердить новое введенное значение. Если он не подтвердит, я хочу восстановить последнее значение.

В настоящее время я делаю как в следующем примере:

procedure  TForm1.FldOnValidate(AField : TField);
begin
  if(MessageDlg('Are you sure?', mtConfirmation, [mbYes, mbNo], 0) = mrNo) then
  begin
    Abort;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Dst : TClientDataSet;
  Dsc : TDataSource;
  Fld : TStringField;
  Grid : TDBGrid;
begin
  //dataset
  Dst := TClientDataSet.Create(Self);
  Dst.FieldDefs.Add('TEST', ftString, 20);
  Dst.CreateDataSet();
  Dst.Active := True;
  Fld := Dst.Fields[0] as TStringField;
  Dst.Append();
  Fld.AsString := 'a';
  Dst.Post();
  Fld.OnValidate := FldOnValidate;

  //datasource
  Dsc := TDataSource.Create(Self);
  Dsc.DataSet := Dst;

  //grid
  Grid := TDBGrid.Create(Self);
  Grid.DataSource := Dsc;
  Grid.Columns.Add.FieldName := Fld.FieldName;
  Grid.Align := alClient;
  Grid.Parent := Self;
end;

Стадии испытаний:

  1. Запустить приложение
  2. Тип 'b'
  3. Нажмите клавишу «Ввод»
  4. Нажмите кнопку «Да»
  5. Тип 'c'
  6. Нажмите клавишу «Ввод»
  7. Нажмите кнопку «Нет»
  8. Нажмите клавишу «Esc»

Значение 'b' будет восстановлено.

Я хочу избежать пункта 8, когда пользователь нажимает кнопку 'No', я хотел бы автоматически сбросить предыдущее значение.

Попытка:

Я пробовал следующим образом, но OldValue - это 'c' (и я не думаю, что это правильный способ делать то, что мне нужно).

procedure  TForm1.FldOnValidate(AField : TField);
begin
  if(MessageDlg('Are you sure?', mtConfirmation, [mbYes, mbNo], 0) = mrNo) then
  begin
    AField.OnValidate := nil;
    try
      AField.AsVariant := AField.OldValue;
    finally
      AField.OnValidate := FldOnValidate;
    end;
    Abort;
  end;
end;

1 Ответ

0 голосов
/ 10 января 2019

Используйте TField.DataSet.Cancel как

procedure  TForm1.FldOnValidate(AField : TField);
begin
  if MessageDlg('Are you sure?', mtConfirmation, [mbYes, mbNo], 0) = mrNo then
      Sender.DataSet.Cancel;
end;
  • Если при нажатии кнопки Да обработчик события OnValidate не вызывает исключение, данные записываются в буфер текущей записи, а затем вызывается обработчик события OnChange.

  • Если нажата кнопка Нет, то будет вызвана процедура Cancel, и все изменения активной записи, если эти изменения еще не опубликованы, будут отменены.

Почему?

С docs

Чтобы отклонить текущее значение поля из обработчика события OnValidate, вызовите исключение.

Итак, поскольку вы не хотите вызывать исключение, это единственный способ сделать это.

Обработчик события OnValidate предназначен для проверки данных, а не для подтверждения.

Это будет легко, если вы используете новейшие версии Delphi, потому что он предоставляет


UPDATE:

  if MessageDlg('Validate?', mtConfirmation, [mbYes, mbNo], 0) = mrNo then
    Sender.DataSet.Cancel
      else
        Sender.DataSet.Post;

Шаги:

  • Введите 'b' и нажмите Yes
  • Введите 'c' и нажмите No
  • Значение вернется к 'b', как вы хотите

Протестировано в Delphi 10 с использованием TFDMemTable .

...