Может ли Delphi TField.OnValidate восстановить исходное значение, не вызывая исключения? - PullRequest
0 голосов
/ 18 октября 2018

Я обычно реализую логику проверки как:

procedure TMyDM.IBQueryAMOUNTValidate(
  Sender: TField);
begin
  inherited;
  if Sender.AsFloat>100
    then raise Exception.Create('Amount is too large!');
end;

Вопрос в том, есть ли шанс не повысить Exception в OnValidate (что останавливает дальнейшую обработку), но восстановить молча оригинальное значениев OnValidate и перейдите к OnChange, CheckBrowseMode и всем обновлениям графического интерфейса, которые вызываются CheckBrowseMode / Post?

Конечно, я знаю, что всегда могу заменить OnValidate логика с OnChange логика, которая обрабатывает OldValue и NewValue, но мне кажется, что код будет чище, я придерживаюсь OnValidate.

Ответы [ 2 ]

0 голосов
/ 18 октября 2018

Не используйте OnValidate для выполнения каких-либо действий, кроме создания исключения для отклонения значения Sender.

Чтобы понять почему, настройте простое тестовое приложение, состоящее из TClientDataSet с полямиID (целое число) и имя (строка (20)), TDataSource, TDBNavigator, TDBGrid и TDBEdit для поля имени.Добавьте следующий код:

procedure TForm1.ClientDataSet1NameValidate(Sender: TField);
begin
  if Sender.AsString = 'x' then
    Sender.DataSet.Cancel;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ClientDataSet1.CreateDataSet;
  ClientDataSet1.InsertRecord([1, 'a']);
  ClientDataSet1.InsertRecord([2, 'b']);
  ClientDataSet1.InsertRecord([3, 'c']);
end;

Скомпилируйте, запустите и введите 'x' (без кавычек) в DBEdit.Затем нажмите «Сохранить» в DBNavigator.

Обратите внимание, что редактирование отменено, но символ «x» остается в DBEdit.Это в Delphi 10.2.3, кстати.Еще в дни D7 было еще хуже - неправильная строка в сетке БД показала бы 'x'!

Другое дело, что OnValidate никогда не вызывается в методах TDataSet, только потомки, напримерTClientDataSet.Таким образом, нет гарантии, что в целом OnValidate будет вызван вообще или в нужное время - это зависит от автора типа набора данных, чтобы сделать это правильно.

Так что я думаю, что ответ на ваш вопрос:«Нет», оставьте OnValidate, чтобы вызывать исключения, но не более.

0 голосов
/ 18 октября 2018

Мне кажется, единственная цель события OnValidate - вызывать исключения.Из справки Delphi (http://docwiki.embarcadero.com/Libraries/Berlin/en/Data.DB.TField.OnValidate):

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

Для задач проверки я использую событие OnSetText, которое дает мне возможность молча восстановить исходное значение, если новое неприемлемый.

...