I'm experimenting with a simple ClientDataSet project that uses a TADTField named Address which contains two subfields, Line1 and City, both of which are strings, size 20. THe CDS is connected to a DBGrid and DBNavigator.
If I set up the CDS using TFieldDefs in the Object Inspector and the ChildDefs property of the ADT field, the project compiles and executes fine.
However, if I try to set up the ATD field and its children in code, I get two problems:
Unlike when I use the FieldDefs method, the ATD "cell" doesn't appear in the DBGrid, so the Line1 and City sub-fields dont display inside it. Instead they appear as ordinary fields and they are duplicated. There is one "Line1" column, then a "City" one, then another "Line1" ...
When I close the form, I get a "double-free" AV inside a second (?) call to TFields.Destroy.
Obvioulsly I'm doing something wrong but I can't see what it is.
Here's my code :
procedure TForm1.FormCreate(Sender: TObject);
var
ADTField : TADTField;
Field : TField;
begin
// at this point, the clientDataSet has no TFields or TFieldDefs
Field := TIntegerField.Create(nil);
Field.FieldName := 'ID';
Field.DataSet := ClientDataset1;
ADTField := TADTField.Create(nil);
ADTField.FieldName := 'Address';
ADTField.DataSet := ClientDataset1;
Field := TStringField.Create(nil);
Field.FieldName := 'Line1';
Field.Size := 20;
Field.DataSet := ClientDataset1;
ADTField.Fields.Add(Field);
Field := TStringField.Create(nil);
Field.FieldName := 'City';
Field.Size := 20;
Field.DataSet := ClientDataset1;
ADTField.Fields.Add(Field);
ClientDataset1.CreateDataSet;
ClientDataset1.Insert;
ClientDataset1.FieldByName('ID').AsInteger := 1;
try
ADTField.Fields.FieldByName('Line1').AsString := '1, Railway Cuttings';
ADTField.Fields.FieldByName('City').AsString := 'London';
except
end;
ClientDataset1.Post;
end;
That's the entire code of the project. I'm using D7.
I remember being foxed by something similar when I first tried out ADT fields: although the TFieldDefs editor in the IDE has an obvious way to add child FieldDefs to an TADTField, there's no counterpart in the IDE's TFields editor.
Anyway, I think you're not quite "parenting" the two fields that you want to be children of the ADT one correctly. Instead of calling ADTField.Fields.Add
, you need to do it via the field itself, by setting its ParentField
property:
Field := TStringField.Create(ClientDataset1);
Field.FieldName := 'Line1';
Field.Size := 20;
Field.DataSet := ClientDataset1;
// ADTField.Fields.Add(Field);
Field.ParentField := ADTField;
And that btw is how you would do it in the IDE if you were setting up TFields instead of TFieldDefs. You'd create your Line1
and City
fields in the ordinary way using the TFields editor, then select them in turn on the OI and set their ParentField
property. I think you'll find that they and the Address
field will then display in your grid correctly and the AV on shutdown will go away.