在Delphi中,我该怎么做才能在任何打开的表单上获取链接到数据集字段的数据感知控件列表?
谢谢
答案 0 :(得分:4)
以下内容基于我对此问题的回答:How to find out which DB-Aware controls are linked to a TDataSource? 哪个询问如何找到将哪些数据库感知控件链接到给定的数据源。
它使用TypInfo.Pas中的传统RTTI,因此实际上可以与 任何版本的Delphi。它不需要更新的RTTI.Pas。下面的示例是在D7中编写和测试的。
截至目前,该答案还不够完整,因为
a)仅涉及列出容器对象中的哪些组件 (例如Form或DataModule)以db感知的方式链接到给定的数据集,但对其进行了扩展 查找哪些控件链接到数据集的特定字段;和
b)假定db-aware控件遵循Delphi约定
DataSource
字段,如果控件是在特定字段上运行的控件
数据集(例如TDBEdit,而不是TDBGrid)中的一个DataField
。
内联注释中解释了代码的工作方式;基本上,迭代
容器中的组件查找数据源,然后检查它们是否为
链接到给定的数据集,然后查找指定数据源的控件
在其DataSource
字段中(如果有),并提取DataField
的值
属性,如果控件是具有一个控件的类型。在明显的待办事项上
扩展代码以覆盖数据集和/或数据集的情况
与支持db的控件位于不同的容器(例如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
所以我希望很明显它应该有能力,还有更多 工作,做您想要的。现在,我将其留给读者练习。
代码
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;
由于感兴趣的项目可能分散在不同的表单/数据模块中,
您可以使用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;