我有一个由主窗体、框架和数据模块组成的应用程序。当创建主表单时,我还创建了包含数据模块中表中字段的框架。所以主要的表单代码是:
unit main;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
FraDtl;
type
TfrmMain = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
FFraDtl: TfraDetail;
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
procedure TfrmMain.FormCreate(Sender: TObject);
begin
FFraDtl := TfraDetail.Create(Self);
FFraDtl.Parent := Self;
end;
end.
帧的代码是这样的:
unit FraDtl;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
database, cxGraphics, cxControls, cxLookAndFeels, cxLookAndFeelPainters,
cxContainer, cxEdit, cxTextEdit, cxDBEdit, Vcl.StdCtrls, dxSkinsCore,
cxNavigator, cxDBNavigator;
type
TfraDetail = class(TFrame)
lblCognome: TLabel;
edtCognome: TcxDBTextEdit;
lblNome: TLabel;
edtNome: TcxDBTextEdit;
cxDBNavigator1: TcxDBNavigator;
private
{ Private declarations }
public
{ Public declarations }
end;
implementation
{$R *.dfm}
end.
数据模块的代码是:
unit database;
interface
uses
System.SysUtils, System.Classes, Data.DB, DBAccess, MSAccess, MemDS,
dxSkinsCore, cxClasses, cxLookAndFeels, dxSkinsForm;
type
TdmData = class(TDataModule)
Connection: TMSConnection;
tblAutori: TMSTable;
dsAutori: TMSDataSource;
fAut_IdAutore: TIntegerField;
fAut_Cognome: TStringField;
fAut_Nome: TStringField;
fAut_Nominativo: TStringField;
SkinController: TdxSkinController;
procedure DataModuleCreate(Sender: TObject);
procedure DataModuleDestroy(Sender: TObject);
procedure dsAutoriStateChange(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
dmData: TdmData;
implementation
{$R *.dfm}
procedure TdmData.DataModuleCreate(Sender: TObject);
begin
tblAutori.Open;
end;
procedure TdmData.DataModuleDestroy(Sender: TObject);
begin
tblAutori.Close;
end;
procedure TdmData.dsAutoriStateChange(Sender: TObject);
begin
// Some stuff
end;
end.
我想调用dsAutoriStateChange事件被激发时帧中存在的过程。有办法做到这一点吗?
我想调用dsAutoriStateChange事件被激发时帧中存在的过程。
你可以使用这样的代码:
unit database;
....
implementation
uses FraDtl;
procedure TdmData.dsAutoriStateChange(Sender: TObject);
begin
FraDtl.SomeProcedure;
end;
或者,如果你想访问实际的实例化框架,你可以访问主单元。
unit database;
....
implementation
uses main; //circular reference allowed in implementation
procedure TdmData.dsAutoriStateChange(Sender: TObject);
begin
frmMain.FrameDetail.DoSomething(Sender);
end;
在这种情况下,您需要向frmMain
添加一个公开框架的公共属性。
TfrmMain = class(TForm)
...
public
property FrameDetail: TFraDetail read FFraDtl;
警告
数据模块和表单之间的这种硬耦合被认为是糟糕的编程实践
松耦合良好
硬耦合是糟糕的
最好对主窗体内的数据源使用事件处理程序,或者如果无法向TdmData
添加由主窗体根据需要更新的其他属性,则使用事件处理器
事件处理程序dsAutoriStateChange
然后可以访问这些属性,而不必在帧的私有部分中四处走动。