Search code examples
delphipropertiescomponentscascadingdropdown

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?


Solution

  • 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.