Как получить значение, вызвавшее ошибку TDBGridInplaceEdit?

Я пытаюсь написать обработчик исключений, который отображает удобные для пользователя сообщения. Я не знаю, как получить значение данных "Newly Entered", которое вызвало ошибку TDBGridInplaceEdit.

Например:
У меня есть DBGrid, загруженный данными. Когда я намеренно изменяю поле PartNo строки №1 на нечисловое значение, чтобы вызвать ошибку TDBGridInplaceEdit... (от: 1313.3 до: 1313..3)... я перехватываю ошибку и отобразить сообщение, но я не могу понять, как получить неправильное значение «1313..3».

введите здесь описание изображения
Номер исходной детали: 1313.3

введите здесь описание изображения
Измененный номер детали: 1313..3 (два десятичных знака)

введите здесь описание изображения
Отображается сообщение об ошибке приложения onException

procedure TMain.ApplicationEvents1Exception(Sender: TObject; E: Exception);
var
  str : string;
begin
  str := sender.ToString;
  str := str + #10;
  str := str + RzDBGrid2.SelectedField.FieldName;
  str := str + #10;
  str := str + VarToStr(RzDBGrid2.SelectedField.Value);
  str := str + #10;
  str := str + e.Message;
  showmessage(str);
  //Application.ShowException(E);
end;

Я хотел бы отформатировать свое собственное сообщение, используя введенное неверное значение «1313..3». Как получить это значение?


person Michael Riley - AKA Gunny    schedule 22.08.2013    source источник
comment
Я недостаточно внимательно прочитал, прежде чем ответить (сейчас я удалил ответ). Вы получаете ошибку EConvertError, которая происходит в процессе присвоения значения и, следовательно, фактически дает сбой в самом RTL и никогда не дойдет до того момента, когда вы сможете получить его через NewValue. Я не знаю, как добраться до значения в этот момент. Лучшим способом, вероятно, было бы установить маску редактирования для самого поля, что в первую очередь предотвратило бы ввод недопустимого значения.   -  person Ken White    schedule 23.08.2013
comment
Я полагаю, что мог бы проанализировать e.Message и таким образом получить значение :)   -  person Michael Riley - AKA Gunny    schedule 23.08.2013
comment
Да, я полагаю. ;-) Я думаю, что вместо этого я бы предотвратил недопустимую запись; это менее хакерски. Если вы все-таки решите пойти по этому пути, вам придется протестировать определенный тип исключения (EConvertError), а затем проанализировать, какой вид преобразования (целое, с плавающей запятой или что-то еще) чтобы знать, что анализировать, а также добавить обработку для других типов исключений (например, отсутствие обязательного поля, ошибка усечения данных (слишком длинная строка) и т. д.) и обрабатывать их также отдельно, а затем общий обработчик для тех, которые вы Мисс.   -  person Ken White    schedule 23.08.2013
comment
Поскольку ошибка не обязательно возникает из cxGrid, но может исходить от каждого элемента управления, привязанного к полю, я бы предпочел отловить проблемы в SetText поля, например. процедура TForm1.ADataSetAFloatFieldSetText(Отправитель: TField; const Text: string); вар ф: Двойной; Начинайте, если не TryStrToFloat(Text,f), затем начинайте повышать Exception.Create('Ошибка: ' +Sender.FieldName + #13#10 + Sender.AsString + #13#10 + Text); конец; конец;   -  person bummi    schedule 23.08.2013
comment
@bummi, вы бы действительно вызвали исключение в обработчике пользовательского интерфейса?   -  person J...    schedule 23.08.2013
comment
@J... проверяя код procedure TField.SetEditText(const Value: string); in DB.pas, я ожидаю, что это одно из желаемых применений для OnSetText   -  person bummi    schedule 23.08.2013
comment
@bummi Я согласен, что это подходящее место для выявления проблемы, мне просто интересно, в чем здесь смысл возбуждать исключение, поскольку, по сути, есть гарантия, что никогда не будет окружающего блока try для его обработки.   -  person J...    schedule 23.08.2013
comment
@J... неверные данные все равно не могут быть назначены. Таким образом, вы можете обработать это здесь с помощью repairing ввода, запросив у пользователя исправленный ввод или просто вызвав ошибку с желаемым форматом, вместо того, чтобы ждать возникновения исключения.   -  person bummi    schedule 23.08.2013
comment
@bummi - я хотел бы использовать вашу технику, но я не знаю, как написать код. Не могли бы вы предоставить ответ (не комментарий) с примером кода, который я могу использовать. Спасибо.   -  person Michael Riley - AKA Gunny    schedule 24.08.2013


Ответы (1)


Если вы сохраняете поля своего набора данных, вы можете определить метод OnSetText для своих полей (дважды щелкните набор данных и выберите «Добавить поля»).

введите здесь описание изображения

Метод может выглядеть так:

procedure TForm1.ADataSetAFloatFieldSetText(Sender: TField; const Text: string);
var
 f:Double;
begin
  if not TryStrToFloat(Text,f) then
      begin
       raise Exception.Create(
                              'Error on: '
                              + #13#10'Dataset: '   + Sender.DataSet.Name 
                              + #13#10'Field: '     + Sender.FieldName 
                              + #13#10'Old Value: ' + Sender.AsString 
                              + #13#10'New Value: ' + Text
                             );
      end;
end;

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

procedure TForm1.ADataSetAfterOpen(DataSet: TDataSet);
Var
 i:Integer;
begin
  for I := 0 to Dataset.FieldCount - 1 do
      begin
        if Dataset.Fields[i].DataType in [ftFloat, ftCurrency, ftBCD] then
           Dataset.Fields[i].OnSetText := ADataSetAFloatFieldSetText;            
      end;
end;
person bummi    schedule 23.08.2013
comment
∞ +1 - Спасибо за ваш пример. Это абсолютно гениально! Я бы никогда не узнал, что это существует. Как вы накопили столько знаний о Delphi? Какие ресурсы вы рекомендуете для получения глубоких знаний? - person Michael Riley - AKA Gunny; 24.08.2013
comment
Просто интересуйтесь свойствами и событиями (источник включен), читайте вопросы и ответы или форумы, практикуйтесь, но, хотя ответ может быть полезным, он далек от блестящего. - person bummi; 24.08.2013