Reputation: 203
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?
Upvotes: 1
Views: 1144
Reputation: 30715
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;
Upvotes: 1