Delphi组件设计,在TFieldDataLink中添加一个字段

Delphi component design, add a field in TFieldDataLink

我正在制作一个新的 vcl 组件,除了一个小细节外,它已经完成了。

该组件使用 TFieldDataLink 制作数据源和数据字段 属性,这工作得很好,问题是我需要第二个字段 属性 在对象检查器中可见,来自同一个数据源作为数据字段。

我真的不需要 'TFields' 属性 可以添加多个字段的地方,一个额外的 FieldProperty 就足够了。

我添加了一个简单的字符串 属性 'DataTypeField': 在我的 class 的已发布部分中的字符串,它工作正常,但你必须在对象检查器中键入值设计时间,如果 属性 让用户从数据链路中选择字段当然会更好。

有人知道怎么做吗?

基本上我的 class 看起来像这样(我删除了很多其他不相关的属性和函数)

TFlexRtfEditor = class(TcxGroupBox)
  Editor: TdxRichEditControl;
private
  FDataLink: TFieldDataLink;
  function GetDataField: string;
  function GetDataSource: TdataSource;
  procedure SetDataField(const Value: string);
  procedure SetDataSource(const Value: TdataSource);
protected
public
published
  property DataField: string read GetDataField write SetDataField;
  property DataSource: TdataSource read GetDataSource write SetDataSource;
end;

在构造函数中 FDataLink := TFieldDataLink.Create; FDataLink.Control := 自我;

在析构函数中 FDataLink.Free;

我想如果我需要第二个字段我需要在类型上创建一个新的 class TFieldDataLink,在已发布部分添加 属性 DataTypeField 并使用此 class 在构造函数 属性 中创建 FDatalink

TFlexRtfEditorDataLink = Class(TFieldDataLink)
private
   fDataTypeField: String;
   procedure SetDataTypeField(const Value: String);
published
   property DataTypeField: String read fDataTypeField write SetDataTypeField;
End; 

FDataLink := TFlexRtfEditorDataLink.Create;
FDataLink.Control := Self;

但是,尽管此编译它不会使对象检查器中的 DataTypeField 属性 可用。

有谁知道我做错了什么? 这是因为 FDataLink 变量在基 class 的私有部分吗?

如果您希望备用数据字段显示在 OI 中,并且 select 它的值来自字段下拉列表 您通常会进入 TDBEdit 的 DataField 属性,这很容易做到, 但是您需要在 IDE 中为它注册一个 属性 编辑器,它才能工作。另外,我认为有一个更容易 比派生 TFieldDataLink 后代更有效的方法。

恐怕我发现你的术语和你试图做的事情的描述有点混乱,所以在下文中,我将把这个备用数据字段称为 AltDataField 以避免混淆. 我还将展示如何添加一个 MainDataField 作为 DataField 属性.

的别名

在主要组件代码中:

type
    TFlexRtfEditor = class(TcxGroupBox)
      //Editor: TdxRichEditControl; omitted for simplicity
    private
      FDataLink: TFieldDataLink;
      FAltDataLink: TFieldDataLink;
      function GetMainDataField: string;
      function GetDataSource: TdataSource;
      procedure SetMainDataField(const Value: string);
      procedure SetDataSource(const Value: TdataSource);
    function GetAltDataField: String;
    procedure SetAltDataField(const Value: String);
    protected
    public
      constructor Create(AOwner : TComponent); override;
      destructor Destroy; override;
    published
      property MainDataField: string read GetMainDataField write SetMainDataField;  // a quasi-alias for DataField
      property DataField: String read GetMainDataField write SetMainDataField;  //  the usual DB-aware component's DataField
      property AltDataField: String read GetAltDataField write SetAltDataField;
      property DataSource: TdataSource read GetDataSource write SetDataSource;
    end;

implementation

constructor TFlexRtfEditor.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FDataLink := TFieldDataLink.Create;
  FAltDataLink := TFieldDataLink.Create;
end;

destructor TFlexRtfEditor.Destroy;
begin
  FAltDataLink.Free;
  FDataLink.Free;
  inherited;
end;

function TFlexRtfEditor.GetMainDataField: string;
begin
  Result := FDataLink.FieldName;
end;

function TFlexRtfEditor.GetDataSource: TdataSource;
begin
  Result := FDataLink.DataSource;
end;

procedure TFlexRtfEditor.SetMainDataField(const Value: string);
begin
  FDataLink.FieldName := Value; //FDataLink.DataSource.DataSet.FindField(Value);
end;

procedure TFlexRtfEditor.SetDataSource(const Value: TdataSource);
begin
  FDataLink.DataSource := Value;
  FAltDataLink.DataSource := Value;
end;

function TFlexRtfEditor.GetAltDataField: String;
begin
  Result := FAltDataLink.FieldName;
end;

procedure TFlexRtfEditor.SetAltDataField(const Value: String);
begin
  FAltDataLink.FieldName := Value;
end;

如您所见,AltDataField 提供了自己的 FieldDataLink, 这比必须派生(和调试)你自己的要简单得多 TFieldDataLink-后代。

在你的组件注册单元中:

interface

uses SysUtils, Classes, DesignIntf, DesignEditors, DSDesign, DBReg, FlexRTFu;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('MA', [TFlexRtfEditor]);
  RegisterPropertyEditor(TypeInfo(string), TComponent, 'MainDataField', TDataFieldProperty);
  RegisterPropertyEditor(TypeInfo(string), TComponent, 'AltDataField', TDataFieldProperty);
end;

end.

顺便说一句,您可能想查看 TDBEdit 的源代码,了解有关组件的属性如何与其 FieldDataLink 交互的一些额外详细信息。

此外,我的包的 Requires 子句如下所示:

requires
  rtl,
  vcl,
  dbrtl,
  vcldb,
  cxLibraryD7,
  dxThemeD7,
  dxCoreD7,
  dxGDIPlusD7,
  vclx,
  cxEditorsD7,
  cxDataD7,
  vcljpg,
  dxSkinBlackD7,
  dxSkinsCoreD7,
  dxSkinBlueD7,
  dxSkinBlueprintD7,
  dxSkinCaramelD7,
  dxSkinCoffeeD7,
  dxSkinDarkRoomD7,
  dxSkinDarkSideD7,
  dxSkinDevExpressDarkStyleD7,
  dxSkinDevExpressStyleD7,
  dxSkinFoggyD7,
  dxSkinGlassOceansD7,
  dxSkinHighContrastD7,
  dxSkiniMaginaryD7,
  dxSkinLilianD7,
  dxSkinLiquidSkyD7,
  dxSkinLondonLiquidSkyD7,
  dxSkinMcSkinD7,
  dxSkinMetropolisD7,
  dxSkinMetropolisDarkD7,
  dxSkinMoneyTwinsD7,
  dxSkinOffice2007BlackD7,
  dxSkinOffice2007BlueD7,
  dxSkinOffice2007GreenD7,
  dxSkinOffice2007PinkD7,
  dxSkinOffice2007SilverD7,
  dxSkinOffice2010BlackD7,
  dxSkinOffice2010BlueD7,
  dxSkinOffice2010SilverD7,
  dxSkinOffice2013DarkGrayD7,
  dxSkinOffice2013LightGrayD7,
  dxSkinOffice2013WhiteD7,
  dxSkinPumpkinD7,
  dxSkinSevenClassicD7,
  dxSkinSevenD7,
  dxSkinSharpD7,
  dxSkinSharpPlusD7,
  dxSkinSilverD7,
  dxSkinSpringTimeD7,
  dxSkinStardustD7,
  dxSkinSummer2008D7,
  dxSkinTheAsphaltWorldD7,
  dxSkinValentineD7,
  dxSkinVS2010D7,
  dxSkinWhiteprintD7,
  dxSkinXmas2008BlueD7,
  designide,
  vclactnband,
  dcldb,
  vcldesigner,
  designdgm,
  dclstd;