Federico Pessina
Federico Pessina

Reputation: 209

Delphi - Populate Property editor dropdown with list?

I'm developing a component. This component has a TDataSource property and a TSecondaryPathsList property. TSecondaryPathsList is declared as follow:

  TSecondaryPathListItem = Class(TCollectionItem)
    private
      fDataField: string;
      fPathPrefixParameter: String;
      procedure SetDataField(Value: string);
      procedure SetPathPrefixParameter(Value: String);
    published
      property DataField: string read fDataField write SetDataField;
      property PathPrefixParameter: String read fPathPrefixParameter write SetPathPrefixParameter;
  End;

  TSecondaryPathsList = class(TOwnedCollection)
  private
    function GetItem(Index: Integer): TSecondaryPathListItem;
    procedure SetItem(Index: Integer; Value: TSecondaryPathListItem);
  public
    function Add: TSecondaryPathListItem;
    property Items[Index: Integer]: TSecondaryPathListItem read GetItem write SetItem; default;
  end;

I don't want it to have a DataSource Property. How can i implement the TSecondaryPathListItem.DataField property, to make it be a dropDown list (in the property editor), displaying Component's DataSource.DataSet fields?

Upvotes: 0

Views: 1145

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 597205

Your DataSource and DataField properties are in separate classes, so you will have to write and register a custom property editor for your DataField property to link them together. You can use Delphi's standard TDataFieldProperty class as a base for your editor. TDataFieldProperty normally looks for a DataSource: TDataSource property (name is customizable) in the same class that the DataField property is declared in, but you can tweak it to retrieve the TDataSource object from your main component instead.

Create a design-time package that requires the IDE's designide and dcldb packages, and your component's runtime package. Implement a class that derives from TDataFieldProperty and overrides its virtual GetValueList() method, like this:

unit MyDsgnTimeUnit;

interface

uses
  Classes, DesignIntf, DesignEditors, DBReg;

type
  TSecondaryPathListItemDataFieldProperty = class(TDataFieldProperty)
  public
    procedure GetValueList(List: TStrings); override;
  end;

procedure Register;

implementation

uses
  DB, MyComponentUnit;

procedure TSecondaryPathListItemDataFieldProperty.GetValueList(List: TStrings);
var
  Item: TSecondaryPathListItem;
  DataSource: TDataSource; 
begin
  Item := GetComponent(0) as TSecondaryPathListItem;

  DataSource := GetObjectProp(Item.Collection.Owner, GetDataSourcePropName) as TDataSource;
  // alternatively:
  // DataSource := (Item.Collection.Owner as TMyComponent).DataSource;

  if (DataSource <> nil) and (DataSource.DataSet <> nil) then
    DataSource.DataSet.GetFieldNames(List);
end;

procedure Register;
begin
  RegisterPropertyEditor(TypeInfo(string), TSecondaryPathListItem, 'DataField', TSecondaryPathListItemDataFieldProperty);
end;

end.

Now you can install the design-time package into the IDE, and your DataField property should display a drop-down list filled with field names from whatever TDataSource is assigned to your component.

Upvotes: 2

Related Questions