1
votes

I am making a new vcl component, which is kinda finished except for one small detail.

The component uses TFieldDataLink to make a Datasource and Datafield property, this is working just fine, the problem is i need a second field property visible in the object inspector, from the same Datasource as the DataField.

I don't really need a 'TFields' property where you can add multiple fields, one additional FieldProperty is enough.

I added a simple string property 'DataTypeField': String in the published section of my class, which works fine, but you have to type the value in the object inspector in design time and it would of course be better if the property would let the user pick the field from the Datalink.

Does anyone have an idea how to do that?

Basicly my class looks like this (i have removed lots of other irrelevant properties and functions)

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;

in constructor FDataLink := TFieldDataLink.Create; FDataLink.Control := Self;

in destructor FDataLink.Free;

I figured if i needed a second field i would need to make a new class, on type TFieldDataLink, add the property DataTypeField in the published section and use this class to create the FDatalink property in the constructor

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;

But although this compiles it doesn't make the DataTypeField property available in the object inspector.

Does anyone know what i'm doing wrong? Is this because the FDataLink variable is in the private section of the base class?

1

1 Answers

1
votes

If you want your alternate DataField to show up in the OI and select its value from the drop-down list of fields you would usually get in the DataField property of a TDBEdit, this is fairly easy to do, but you need to register a property editor for it in the IDE for it to work. Also, I think there is an easier way to do it than deriving a TFieldDataLink descendant.

I'm afraid I found your terminology and description of what you are trying to do a bit confusing, so in the following, I'm going to refer to this alternate DataField as AltDataField to avoid confusion. I'm also going to show how to add a MainDataField that works as an alias for the DataField property.

In the main component code:

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;

As you can see, the AltDataField is provided with its own FieldDataLink, which is far simpler than having to to derive (and debug) your own TFieldDataLink-descendant.

In your component registration unit:

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.

Btw, you might want to look at the source code of TDBEdit for some extra details of how the component's properties interact with its FieldDataLink.

Also btw, my package's Requires clause looks like this:

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;