Sunday, November 01, 2009

Using TDBEdit to handle date fields

If you try to link a date field with a TDBEdit, when an user inserts an invalid date, the control reacts with a non user friendly exception message. So, for long time, i used a TMaskEdit to edit date values and then update manually the dataset.
After some debate about TMaskEdit in the mail list i tried to workaround this problem.

The first think i did was to set the EditMask property to !99/99/9999;1;_ and hardcode the ShortDateFormat with a compatible format, e.g. 'dd/mm/yyyy'.

To validate the value inserted i created a handler to be linked to TDBEdit OnExit event(the color setting is optional):

var
D: TDateTime;
DateEdit: TDBEdit;
begin
DateEdit := Sender as TDBEdit;
if not TryStrToDate(DateEdit.Text, D) then
begin
ShowMessage(DateEdit.Text + ' is not a valid date');
DateEdit.Clear;
DateEdit.Color := clRed;
//or set a default value
//DateEdit.Text := '10/10/1900';
end
else
DateEdit.Color := clWindow;
end;

So you clear the TDBEdit and get a empty string that is valid value right? Not so fast. The message dialog will trigger an KillFocus message updating the Dataset with the old (and invalid) value. Calling ShowMessage after Clear does not help because the the control will try to update the dataset with " / / ", that is also not a valid value.

The solution i found was to handle the OnSetText event of the date field to skip all invalid values:

var
D: TDateTime;
begin
if not TryStrToDate(aText, D) then
Sender.Value := Null
else
Sender.AsDateTime := D;
end;

With this approach is possible to allow date edition with masks safely.

However, setting events for each TDBEdit and date field is annoying, so i created an TDBEdit descendant to handle this issue. It can be found in the LuiControls package (svn version).

In time:
  • Rx package has a TDBDateEdit component, but it does not allow editing with masks and don't manage invalid dates.
  • It's required a recent (post 0.9.28) svn version because of a bug in TMaskEdit in the earlier versions

1 comment:

Anonymous said...

Olá Luiz,

Eu estou me desligando um pouco do data-aware, mas estou acompanhando as tuas dicas, para divulgar para os amigos ;) Acabei de indicar esta aqui para um brother.

Desculpe o comentário em português, hehe... :)

Abraços,

Silvio Clécio