Title: Enumerate all DB-aware VCL components linked to a datasource
Question: Often it is practical to enumerate all db-aware components that are connected to a particular datasource. In my case, I had to be able to automatically switch between Unicode and UTF-8 depending on the database engine.
Answer:
The following procedure will iterate through all db-aware
components connected to a datasource, and call a user-defined
callback method for each component found.
UNIT enum_Dbaware;
interface uses classes,db,dbctrls;
Type tEnumerate_Db_Aware = procedure (component: tcomponent;
fieldname:string; tds:tdataset; tso:tdatasource;
fdl: tfielddatalink) OF OBJECT;
Procedure Enumerate_Db_Aware (ds : tdatasource; enumerate : tEnumerate_DB_Aware);
implementation
// tweak to get at protected "datalinks" property
Type tTweakDatasource=class(tdatasource)
end;
Procedure Enumerate_Db_Aware (ds : tdatasource; enumerate : tEnumerate_DB_Aware);
var das : tdataset;
t : tobject;
fdl : tfielddatalink;
fn : string;
component : tcomponent;
i : integer;
begin
das:=ds.dataset;
for i:=0 to tTweakDataSource(ds).datalinks.count-1 do
begin
t:=tTweakDataSource(ds).datalinks[i];
if t IS tFielddatalink then
begin
fdl :=tfielddatalink(t);
component :=fdl.control;
fn :=fdl.fieldname;
enumerate (component,fn,das,ds,fdl);
end;
end;
end;
end.
//****************************************************************
Example:
This code snippet will force all components of type
tElWideDBEdit (Yes I use the "LMD Elpack" component suite)
to use "UTF8" string format if the attached database field
isn't a widestring Unicode field.
UTF8 is a packed unicode format that can be stored in a normal
Ansistring. This way, the form will support unicode on any database
engine type.
The "Afteropen" Event is the right place to call the
procedure.
procedure TMyForm.dataset1AfterOpen(DataSet: TDataSet);
begin
Enumerate_Db_Aware (datasource1, enumerate);
end;
procedure TMyForm.Enumerate(component: tcomponent;
fieldname:string; tds:tdataset;
tso:tdatasource; fdl: tfielddatalink);
VAR field : tfield;
begin
field:=tds.fields.fieldbyname(fieldname);
if component IS tElWideDBEdit then
begin
if (field IS tstringfield) and not
(field is tWidestringfield) then
tElWideDBEdit (component).UnicodeMode:=UMForceUtf8;
end;
end;