I have DataSource1 (TDataSource)
, and there are some DB-Aware controls linked to it (via SomeDBControl.DataSource=DataSource1
)
How can I find out (enumerate) in code which controls are linked to a given TDataSource?
I have DataSource1 (TDataSource)
, and there are some DB-Aware controls linked to it (via SomeDBControl.DataSource=DataSource1
)
How can I find out (enumerate) in code which controls are linked to a given TDataSource?
The code below, which uses RTTI, works for me in D7 to list the components which have a DataSource or MasterSource property by recursively searching a container object (i.e. the form and its components).
(Obviously, you could do similar for any other forms/datamodules you're interested in)
Update #1: The original version of this answer produced a list of every component on a form and the name of its DataSource/MasterSource, if any. I've changed it to provide a better match with what you ask in the body of your q).
Update #2: This fixes a couple of slips in the Update #1 version, and re-implements the HasDataSource function in a way which avoids generating an exception when examining components which don't have a DataSource/MasterSource property.
function HasDataSource(AComponent : TComponent; var ADataSource : TDataSource) : Boolean;
function GetDataSource(APropName : String) : TDataSource;
var
AObject : TObject;
PInfo : PPropInfo;
begin
Result := Nil;
PInfo := GetPropInfo(AComponent, APropName);
if PInfo = Nil then
exit;
AObject := GetObjectProp(AComponent, PInfo);
Result := TDataSource(AObject);
end;
begin
Result := False;
ADataSource := GetDataSource('DataSource');
if ADataSource <> Nil then
Result := True;
if Result then exit;
ADataSource := GetDataSource('MasterSource');
if ADataSource <> Nil then
Result := True;
end;
procedure TForm1.Log(Msg: String);
begin
Memo1.Lines.Add(Msg);
end;
procedure TForm1.FindDataSourceObjects(AContainer : TComponent);
var
i : Integer;
ADataSource : TDataSource;
procedure LogDataSourceName(AContainer : TComponent);
begin
Log(AContainer.Name + ' Datasource: ' + ADataSource.Name);
end;
begin
if HasDataSource(AContainer, ADataSource) then
LogDataSourceName(AContainer);
for i := 0 to AContainer.ComponentCount - 1 do begin
FindDataSourceObjects(AContainer.Components[i]);
end;
end;
procedure TForm1.btnFindClick(Sender: TObject);
begin
FindDataSourceObjects(Self);
end;
The DFM of my form is
object Form1: TForm1
Left = 195
Top = 124
Width = 623
Height = 303
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object DBText1: TDBText
Left = 307
Top = 56
Width = 65
Height = 17
DataSource = DataSource1
end
object Panel1: TPanel
Left = 307
Top = 80
Width = 281
Height = 161
Caption = 'Panel1'
TabOrder = 0
object DBText2: TDBText
Left = 24
Top = 64
Width = 65
Height = 17
DataSource = DataSource2
end
end
object Memo1: TMemo
Left = 8
Top = 16
Width = 281
Height = 225
TabOrder = 1
end
object btnFind: TButton
Left = 307
Top = 16
Width = 75
Height = 25
Caption = 'Find'
TabOrder = 2
OnClick = btnFindClick
end
object DataSource1: TDataSource
DataSet = ClientDataSet1
Left = 448
Top = 16
end
object DataSource2: TDataSource
DataSet = ClientDataSet2
Left = 544
Top = 16
end
object ClientDataSet1: TClientDataSet
Aggregates = <>
Params = <>
Left = 408
Top = 16
end
object ClientDataSet2: TClientDataSet
Aggregates = <>
MasterSource = DataSource1
PacketRecords = 0
Params = <>
Left = 496
Top = 16
end
end
Result := (IsPublishedProp(AComponent, 'DataSource') and PropIsType(AComponent, 'DataSource', tkClass) and (GetObjectProp(AComponent, 'DataSource', TDataSource) = ADataSource)) or...
. How I loved that old style RTTI :) –
Snobbery if PInfo^.PropType^^.Kind = tkClass
) and if so, whether the object that you obtain is really of type TDataSource
(addressing the typecast). If someone would make an (evil :-) component that would have published DataSource
property of type e.g. Integer
, or the object class would differ from TDataSource
, the function would fail. [+1ed already since RTTI is the right way to go] –
Snobbery © 2022 - 2024 — McMap. All rights reserved.
DataLinks
, there is no reliable way to get access to instances for all types of linked controls. The only remaining way I can think of is iterate all the controls and ask theirDataSource
property. @MartynA, unfortunately wasn't... – Snobbery