在我的项目中有一个TADOQuery tdm_Company,它填充了一组字段,在适当的地方提供了适当的标签和字段设置为visible = false。查询返回单个结果。
我有一个详细信息屏幕,需要一堆标签和编辑这些字段的文本框。
是否可以在编辑器中自动生成这些?如果我需要那些控件来自DevExpress组件(例如TcxDBTextEdit和TcxLabel),该怎么办?
答案 0 :(得分:1)
我从来没有尝试过这个,但有(或者是 - 对不起,无法检查)Database Form Wizard。如果您希望拥有除向导生成的控件之外的其他控件,则可以在以后更改这些控件,例如: GExperts' Replace Components
答案 1 :(得分:1)
在一个非常类似的情况下(返回显示来自实体的联系人数据的单个记录的查询 - 公司,客户等),我们使用DevExpress的 TcxDBVerticalGrid 。当它显示一堆代表单个对象的数据时,它可以更好地扩展并且更灵活(特别是在调整表单大小时)。
当然,你不依赖于上面的组件,你可以用(几乎)任何垂直网格/ DBIspector获得好的结果但是因为你问了一个DevExpress组件我给你上面的解决方案。
HTH
答案 2 :(得分:1)
很久以前我实际创建了自己的向导,基于我为我的FrameWork编写的实际自定义表单。当显示向导的对话框时,它将显示网格中的所有字段,并允许用户指示应该使用哪个组件来显示该字段。
在我的情况下,根据字段类型,它预先填充了特定的组件(例如,TDateTime字段的TcxDateEdit,...)。用户仍然可以更改它,并指出他想要添加到表单的字段。一旦用户关闭表单,只需在所有字段上进行迭代并创建相应的控件。
通过我的代码搜索并找到了回复:
{ Custom Devia Development Framework RecordView Module which adds functionality to
create the DB Aware Controls for the RecordView }
TDevFrameWorkRecordViewModule = class( TCustomModule )
protected
procedure CreateDBAwareComponents( aParent : TComponent; aDataSource : TDataSource; aFields : TFields; aFieldDefs : TFieldDefs ); virtual;
function DefaultWizardClass : TDBAwareControlWizardClass; virtual;
function DefaultLabelClass : TComponentClass; virtual;
function MaxFieldCaptionLength ( aFields : TFields ) : Integer; virtual;
protected
function GetSelectedComponents : IDesignerSelections;
function GetSelectedControl : TControl;
property SelectedControl : TControl read GetSelectedControl;
property SelectedComponents : IDesignerSelections read GetSelectedComponents;
public
procedure DevAddDBAwareComponentsWizard( aParent : TControl ); virtual;
procedure ExecuteVerb(Index: Integer); override;
function GetVerb(Index: Integer): string; override;
function GetVerbCount: Integer; override;
end;
...
procedure TDevFrameWorkRecordViewModule.CreateDBAwareComponents(
aParent : TComponent; aDataSource : TDataSource; aFields : TFields; aFieldDefs : TFieldDefs );
var
lcv : Integer;
aLabel : TControl;
aEdit : TWinControl;
aDataBinding : TcxDBEditDataBinding;
aTop , aLeft : Integer;
aWidth : Integer;
aMaxCaptionWidth: Integer;
aDBLeft : Integer;
aRecordView : IDevFrameWorkRecordView;
aDBAwareClass : TComponentClass;
aDBAwareVisible : Boolean;
aWizardForm : TfrmDevFrameWorkAddDataAwareControlsWizard;
begin
{ First make sure the procedure was triggered on a FrameWorkRecordView }
if ( Supports( Root, IDevFrameWorkRecordView, aRecordView ) ) then
begin
{ Now Create and Show the wizard so the user can specify all the options }
aWizardForm := DefaultWizardClass.Create( Nil );
try
aWizardForm.RecordDataSet := aRecordView.DataSource.DataSet;
aWizardForm.InitialiseSettings;
{ If the user closed the Wizard using the OK button, we can continue the
process }
if ( aWizardForm.ShowModal = mrOK ) then
begin
{ By default the label components should start at 8,8 in the Parent Container }
aTop := 8;
aLeft := 8;
aWidth:= 121;
aMaxCaptionWidth := MaxFieldCaptionLength( aFields );
{ Now set the intial Left Position for our DBAware controls according
to the MaxCaptionWidth }
aDBLeft := 24 + ( ( ( aMaxCaptionWidth div 8 ) + 1 ) * 8 );
{ Loop over all fields to create the Label and DBAwareComponent }
for lcv := 0 to Pred( aFields.Count ) do
begin
{ Get some settings from the Wizard form }
aDBAwareClass := aWizardForm.GetDBAwareComponentClass( aFields[ lcv ] );
aDBAwareVisible := aWizardForm.GetDBAwareComponentVisible( aFields[ lcv ] );
{ Only create the components if the user indicated he wants to see them }
if aDBAwareVisible then
begin
{ Now create the Label and the DBAware Control }
aLabel := TControl ( Designer.CreateComponent( DefaultLabelClass, aParent, aLeft , aTop, aMaxCaptionWidth, 17 ) );
aEdit := TWinControl( Designer.CreateComponent( aDBAwareClass, aParent, aDBLeft, aTop, aWidth, 21 ) );
{ Now Set the Label Properties }
aLabel.Name := Designer.UniqueName( 'cxlbl' + aFields[ lcv ].FieldName );
aLabel.HelpType := htKeyWord;
aLabel.HelpKeyword := Root.Name + '.' + aFields[ lcv ].FieldName;
{ Set the additional properties using RTTI }
if ( IsPublishedProp( aLabel, 'FocusControl' ) ) then
begin
SetObjectProp( aLabel, 'FocusControl', aEdit );
end;
if ( IsPublishedProp( aLabel, 'Caption' ) ) then
begin
SetStrProp( aLabel, 'Caption', aFields[ lcv ].DisplayLabel );
end;
{ Now set the Edit Properites }
aEdit.Name := Designer.UniqueName( {'cxlbl' +} aFields[ lcv ].FieldName );
aEdit.HelpType := htKeyWord;
aEdit.HelpKeyword := Root.Name + '.' + aFields[ lcv ].FieldName;
{ Set the additional properties using RTTI }
if ( IsPublishedProp( aEdit, 'DataBinding' ) ) then
begin
aDataBinding := TcxDBEditDataBinding( GetObjectProp( aEdit, 'DataBinding' ) );
SetObjectProp( aDataBinding, 'DataSource', aDataSource );
SetStrProp ( aDataBinding, 'DataField' , aFields[ lcv ].FieldName );
end;
if ( aEdit is TcxCustomDropDownEdit ) then
begin
aEdit.Width := aWidth + 16;
end;
{ Now increment the Top position for the next control }
inc( aTop, ( ( ( aEdit.Height div 8 ) + 1 ) * 8 ) );
end;
end;
end;
finally
FreeAndNil( aWizardForm );
end;
end;
end;
function TDevFrameWorkRecordViewModule.DefaultLabelClass: TComponentClass;
begin
Result := TLabel;
end;
function TDevFrameWorkRecordViewModule.DefaultWizardClass: TDBAwareControlWizardClass;
begin
Result := TfrmDevFrameWorkAddDataAwareControlsWizard;
end;
procedure TDevFrameWorkRecordViewModule.ExecuteVerb(Index: Integer);
var
aSelections : IDesignerSelections;
lcv : Integer;
begin
aSelections := TDesignerSelections.Create;
Designer.GetSelections( aSelections );
for lcv := 0 to Pred( aSelections.Count ) do
begin
{$IFDEF CODESITE}
csFWRecordView.Send( 'aSelection.Items[ lcv ]', aSelections.Items[ lcv ] );
{$ENDIF}
end;
Case Index of
0 : DevAddDBAwareComponentsWizard( SelectedControl );
else Inherited ExecuteVerb( Index );
end;
end;
{*****************************************************************************
This function will be used to return a list of selected components on the
current designer.
@Name TDevFrameWorkRecordViewModule.GetSelectedComponents
@author Devia - Stefaan Lesage
@param None
@return None
@Exception None
@See None
******************************************************************************}
function TDevFrameWorkRecordViewModule.GetSelectedComponents: IDesignerSelections;
begin
Result := TDesignerSelections.Create;
Designer.GetSelections( Result );
end;
function TDevFrameWorkRecordViewModule.GetSelectedControl: TControl;
var
lcv : Integer;
begin
Result := Nil;
if ( Assigned( SelectedComponents ) ) then
begin
if ( SelectedComponents.Count <> 0 ) then
begin
for lcv := 0 to Pred( SelectedComponents.Count ) do
begin
if ( SelectedComponents.Items[ lcv ] is TControl ) then
begin
Result := TControl( SelectedComponents.Items[ lcv ] );
Break;
end;
end;
end;
end;
end;
function TDevFrameWorkRecordViewModule.GetVerb(Index: Integer): string;
begin
Case Index of
0 : Result := 'Dev.AddDataAwareComponents';
end;
end;
function TDevFrameWorkRecordViewModule.GetVerbCount: Integer;
begin
Result := 1;
end;
{*****************************************************************************
This function will determine the length of the Longest field's caption.
@Name TDevFrameWorkRecordViewModule.MaxFieldCaptionLength
@author Devia - Stefaan Lesage
@param None
@return Returns the length of the longest field's catpion.
@Exception None
@See None
******************************************************************************}
function TDevFrameWorkRecordViewModule.MaxFieldCaptionLength(
aFields: TFields): Integer;
var
aMaxCaptionWidth : Integer;
aCanvas : TCanvas;
lcv : Integer;
aCaption : String;
begin
aMaxCaptionWidth := 0;
{ First Determine how long the largest caption will be }
aCanvas := TDevFrameWorkRecordView( Root ).Canvas;
{ Loop over each field to dertermin which caption is the longest one }
for lcv := 0 to Pred( aFields.Count ) do
begin
if ( aFields[ lcv ].DisplayLabel <> '' ) then
begin
aCaption := aFields[ lcv ].DisplayLabel;
end
else
begin
aCaption := aFields[ lcv ].FieldName;
end;
if ( aCanvas.TextWidth( aCaption ) >
aMaxCaptionWidth ) then
begin
aMaxCaptionWidth := aCanvas.TextWidth( aCaption );
end;
end;
{ Return the Length of the Longest Caption }
Result := aMaxCaptionWidth;
end;
procedure TDevFrameWorkRecordViewModule.DevAddDBAwareComponentsWizard( aParent : TControl );
var
aRecordView : IDevFrameWorkRecordView;
aDataSource : TDataSource;
begin
{$IFDEF CODESITE}
csFWRecordView.EnterMethod( Self, 'DevAddDBAwareComponentsWizard' );
{$ENDIF}
if ( Supports( Root, IDevFrameWorkRecordView, aRecordView ) ) then
begin
{$IFDEF CODESITE}
csFWRecordView.SendMsg( csmInfo, 'Root supports I®FrameWorkRecordView' );
{$ENDIF}
aDataSource := TDataSource( Designer.GetComponent( 'srcMain' ) );
if ( Assigned( aDataSource ) ) and
( Assigned( aDataSource.DataSet ) ) then
begin
{$IFDEF CODESITE}
csFWRecordView.SendMsg( csmInfo, 'aRecordView.DataSource Assigned' );
csFWRecordView.SendMsg( csmInfo, 'aRecordView.DataSource.DataSet Assigned' );
{$ENDIF}
CreateDBAwareComponents( aParent, aDataSource, aDataSource.DataSet.Fields, aDataSource.DataSet.FieldDefs );
end;
end;
{$IFDEF CODESITE}
csFWRecordView.ExitMethod( Self, 'DevAddDBAwareComponentsWizard' );
{$ENDIF}
end;
当然这不会为你编译。这是几年前我在Delphi 7中为开发框架编写的内容。它应该让你知道如何实际做到这一点。
此致
斯特凡