以下是基于我对这个问题的回答:如何找出哪些 DB-Aware 控件链接到 TDataSource? 其中询问如何查找哪些 db-aware 控件链接到给定的数据源。
它使用 TypInfo.Pas 中的传统 RTTI,因此几乎可以与任何版本的 Delphi 配合使用。它不需要更新的 RTTI.Pas。下面的示例是在 D7 中编写和测试的。
截至目前,这个答案还不是很完整,因为
a) 它只列出容器对象(例如 Form 或 DataModule)中的哪些组件以 db-aware 方式链接到给定的数据集,但扩展它以查找哪些控件链接到特定字段数据集;和
b) 它假定数据库感知控件遵循具有DataSource字段的 Delphi 约定,如果控件是对数据集的特定字段(例如 TDBEdit,但不是例如 TDBGrid)进行操作的控件,则为DataField一个。
内联注释中解释了代码的工作原理;基本上,它迭代容器中的组件以查找数据源,然后检查它们是否链接到给定的数据集,然后查找在其DataSource字段中指定数据源的控件(如果有),DataField
如果控件是,则提取属性的值一种类型。显而易见的待办事项是扩展代码以涵盖数据集和/或数据集位于与数据库感知控件不同的容器(例如 DataModule)中的情况。
示例项目包括一个 TClientDataSet、TDataSource、TDBGrid 和两个以您期望的方式连接并产生输出的 DBEdits
DataSource: DataSource1 DataSet: ClientDataSet1
DBEdit1 (Classname: TDBEdit) is linked to ClientDataSet1
on datafield: ID
DBEdit2 (Classname: TDBEdit) is linked to ClientDataSet1
on datafield: Name
Run Code Online (Sandbox Code Playgroud)
所以我希望很清楚,它应该能够做更多的工作,做你所要求的。现在,我把它留给读者作为练习。
代码
uses ... typinfo;
procedure TForm1.Log(Msg: String);
begin
Memo1.Lines.Add(Msg);
end;
function DataSourceHasDataSet(ADataSource : TDataSource; ADataSet : TDataSet) : Boolean;
begin
Result := ADataSource.DataSet = ADataSet;
end;
procedure TForm1.FindControlsForDataSet(AContainer : TComponent; ADataSet : TDataSet);
var
i, j : Integer;
ADataSource : TDataSource;
AComponent,
BComponent : TComponent;
AObject : TObject;
PInfo : PPropInfo;
AFieldName : String;
begin
// iterate the container looking for datasources
for i := 0 to AContainer.ComponentCount - 1 do begin
AComponent := AContainer.Components[i];
if AComponent is TDataSource then begin
ADataSource := TDataSource(AComponent);
// Check that ADataSource is linked to our specifiied dataset
if DataSourceHasDataSet(ADataSource, ADataSet) then begin
Log('DataSource: ' + ADataSource.Name + ' DataSet: ' + ADataSet.Name);
// now, iterate the container looking for controls which
// have a DataSource property specifying the found datasource
for j := 0 to AContainer.ComponentCount - 1 do begin
BComponent := AContainer.Components[j];
PInfo := GetPropInfo(BComponent, 'DataSource');
// PInfo will be non-NIL of the BComponent has a DataSource property
if PInfo <> Nil then begin
AObject := GetObjectProp(BComponent, PInfo);
if (AObject <> Nil) then
if (AObject is TDataSource) then begin
Log(BComponent.Name + ' (Classname: ' + BComponent.ClassName + ') is linked to ' + ADataSet.Name);
PInfo := GetPropInfo(BComponent, 'DataField');
if PInfo <> Nil then begin
AFieldName := GetStrProp(BComponent, 'DataField');
Log(' on datafield: ' + AFieldName);
end;
end;
end;
end;
end;
end;
end;
end;
procedure TForm1.btnFindClick(Sender: TObject);
begin
FindControlsForDataSet(Self, ClientDataSet1);
end;
Run Code Online (Sandbox Code Playgroud)
由于感兴趣的项目可能分布在不同的表单/数据模块中,您可以使用Screen对象来列出它们
procedure TForm1.btnFormsClick(Sender: TObject);
var
i : Integer;
begin
for i := 0 to Screen.CustomFormCount - 1 do begin
Log(Screen.CustomForms[i].Name);
end;
for i := 0 to Screen.DataModuleCount - 1 do begin
Log(Screen.DataModules[i].Name);
end;
end;
Run Code Online (Sandbox Code Playgroud)