【问题标题】:How to find out which DB-Aware controls are linked to a TDataSource?如何找出哪些 DB-Aware 控件链接到 TDataSource?
【发布时间】:2014-06-23 08:26:46
【问题描述】:

我有 DataSource1 (TDataSource),并且有一些 DB-Aware 控件链接到它(通过 SomeDBControl.DataSource=DataSource1

如何在代码中找出(枚举)哪些控件链接到给定的 TDataSource?

【问题讨论】:

  • @TLama,DataLinks 是 TDataLink 的列表。 VisualControl 是布尔值。但是哪个控件?
  • @TLama,非常好,使用 TFieldDataLink 我可以访问“Control”属性,但使用 TGridDataLink.FGrid 是私有成员:(如果没有人会给出更好的答案(包括 TDBGrids)我'会接受你的评论。
  • @TLama,我错过了。请作为答案发布,我很乐意接受!
  • 抱歉,从这里收回我所有的 cmets... 对于 DataLinks,没有可靠的方法可以访问所有类型的链接控件的实例。我能想到的唯一剩下的方法是迭代所有控件并询问它们的DataSource 属性。 @MartynA,不幸的是不是...
  • @TLama:哦,好吧。 OP 不能通过查找组件的 DataSource 和 MasterSource 属性来使用旧式 RTTI 吗?

标签: delphi delphi-7


【解决方案1】:

下面的代码使用 RTTI,在 D7 中为我工作,通过递归搜索容器对象(即表单及其组件)列出具有 DataSource 或 MasterSource 属性的组件。

(显然,您可以对您感兴趣的任何其他表单/数据模块执行类似操作)

更新 #1: 此答案的原始版本生成了表单上每个组件的列表及其 DataSource/MasterSource 的名称(如果有)。我已对其进行了更改,以更好地匹配您在 q) 正文中的要求。

更新 #2: 这修复了更新 #1 版本中的几个漏洞,并重新实现了 HasDataSource 函数,以避免在检查没有的组件时生成异常一个 DataSource/MasterSource 属性。

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;

我的表单的 DFM 是

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...。我多么喜欢那种老式的 RTTI :)
  • @TLama:谢谢。困扰我的是,我以前的版本会为没有 DataSource/MasterSource 的组件生成异常,并且一个项目中可能有数百个。我以一种避免这种情况的方式重新编码了我的 HasDataSource 函数,同时只涉及对每个属性名称的属性信息的一次访问。
  • 偏执的方法还会检查属性是否包含一个对象 (if PInfo^.PropType^^.Kind = tkClass),如果是,您获得的对象是否真的是 TDataSource 类型(解决类型转换)。如果有人会制作一个(邪恶 :-) 组件,该组件将发布 DataSource 类型的属性,例如Integer,或者对象类与TDataSource 不同,函数将失败。 [已经 +1 了,因为 RTTI 是正确的选择]
猜你喜欢
  • 2019-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多