I am trying to find the most efficient way of updating a grid (StringGrid or KGrid) from a Delphi/Lazarus FreePascal collection.
One of my collections is as listed below:
{ TEntretien }
TEntretien = class(TCollectionItem)
private
{ private declarations }
FPrenom: string;
FSexe: string;
FSigneDistinctif: string;
FPays: string;
FTotale: integer;
FColumns: integer;
public
{ public declarations }
published
{ published declarations }
property Prenom: string read FPrenom write FPrenom;
property Sexe: string read FSexe write FSexe;
property SigneDistinctif: string read FSigneDistinctif write FSigneDistinctif;
property Pays: string read FPays write FPays;
property Totale: integer read FTotale write FTotale;
end;
{ TEntretiens }
TEntretiens = class(TCollection)
private
{ private declarations }
function GetItem(AIndex: integer): TEntretien;
public
{ public declarations }
constructor Create;
function Add: TEntretien;
property Items[AIndex: integer]: TEntretien read GetItem; default;
end;
I have the following code snippet that I use for updating one of my grids:
// Fill the grid with the results of the query
for intGridRow := 0 to intNumberOfRows - 1 do
begin
for intGridCol := 0 to intNumberOfColumns - 1 do
begin
// Write the rest of the retrieved data into the grid proper USE RTTI HERE??
if intGridCol = 0 then
kgGridName.Cells[intGridCol + kgGridName.FixedCols, intGridRow + kgGridName.FixedRows] :=
AEntretiens[intGridRow].Prenom
else if intGridCol = 1 then
kgGridName.Cells[intGridCol + kgGridName.FixedCols, intGridRow + kgGridName.FixedRows] :=
AEntretiens[intGridRow].Sexe
else if intGridCol = 2 then
kgGridName.Cells[intGridCol + kgGridName.FixedCols, intGridRow + kgGridName.FixedRows] :=
AEntretiens[intGridRow].SigneDistinctif
else if intGridCol = 3 then
kgGridName.Cells[intGridCol + kgGridName.FixedCols, intGridRow + kgGridName.FixedRows] :=
AEntretiens[intGridRow].Pays
else if intGridCol = 4 then
kgGridName.Cells[intGridCol + kgGridName.FixedCols, intGridRow + kgGridName.FixedRows] := IntToStr(AEntretiens[intGridRow].Totale)
end;
end;
This is fine for collections with a small number of fields/properties but I also have collections with up to 40 fields and so the method I use above is too cumbersome.
Is there a more efficient way of doing this? Someone suggested RTTI but I don’t know how to use it.
Thanks a lot,
JDaniel
Here is a Delphi Enhanced RTTI implementation. This is valid from Delphi-2010.
It will search for all readable published properties (in the declared order) and fill the grid with values.
If you have more than integer and strings as properties, add more in the case statement.
As mentioned in the comments by Ken, Enhanced RTTI is not implemented in Lazarus/FreePascal.
A generic solution for all platforms would then be to add a collection item base class with the possibilities to get the property values.
Then your declaration and implementation would look like this :
Just fill in the GetPropertyCount and GetPropertyString implementation part in your TEntretien class.
This way of doing it may seem as inefficient as your example by having to code all property values by hand. But doing as my example is conforming to two basic principles in programming :