Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1589
  • Last Modified:

How to register TValueListEditor property editor for a TStrings property

Hi,

I'm writing a component and I want a property to store key/value pairs.

I declared my member:

FProps : TStrings;


property Props: TStrings read FProps write SetProps;


procedure TMyComponent.SetProps(Value: TStrings);
begin
  FProps .Assign(Value);
end;


I created in Create
FProps := TStringList.Create()

I free it in Destroy:
FProps.Free


Now, after it is built and installed, if I drop it in a form and click on the Props property, I get a String List Editor.
I want a Value List Editor.

So, I'm trying to register the property editor:

  RegisterPropertyEditor( TypeInfo(TStrings), TMyComponent, 'Props',  TValueListEditor);

And I get the error:

E2010 Incompatible types: 'class of TBasePropertyEditor' and 'class of TValueListEditor'


I suppose it is a bit more complex than what I'm doing to get the ValueListEditor to edit my property....




0
fischermx
Asked:
fischermx
1 Solution
 
Geert GruwezOracle dbaCommented:
the property of the component has to be a descendant of TStrings

You register the component, not the property
This should be automatic if you set the property in the published section

0
 
Geert GruwezOracle dbaCommented:
post the declaration of the component for further help

you need to know the difference for the sections private, protected, public and published within a component

To create your own PropertyEditor that's a completely different game
0
 
BdLmCommented:
or do it the other way around

define a descendant of TValueListEditor  as TKeyValueListEditor and
add your strings edit stuff inside that class ....
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
fischermxAuthor Commented:
Geert Gruwez:

I have created other property editors to fill drop down lists in this same component. So, I sort of know how to do that part but.... I don't know about this key/value pairs editor.

I did, of course, put the property as published, that's why I see it in the Object Inspector and I was able to click it!!

Now, you said "This should be automatic if you set the property in the published section"..... so, that mean should I not use the RegisterPropertyEditor?

Should I declare any special unit? may be?
0
 
Geert GruwezOracle dbaCommented:
a descendant of TStrings will have a memo editor by default

if you want a other type of editor, then you use RegisterPropertyEditor

I guess you want the ValueListEditor component to act as your pairs editor in your propertyeditor for that component ?
0
 
fischermxAuthor Commented:
Hi, Geert:

Exactly.

I'm getting a plain Strings List Editor, a single "memo" to type freely in it.
I want to get the editor which is a 2 column grid, with columns titles "Key" and "Value.
I want that.
How do I get it? I swear I googled for this 2 hours yesterday, and all I could find was sample code about using the TValueListEditor alone, not as a property editor.

The part of code I have, I took it from the "Params" property in the TDatabase component from VCL
But they don't provide the code for the registration, so I can't see how do they do it.
0
 
Geert GruwezOracle dbaCommented:
damn, this was staring me right in the eye the whole time, but i figured it out
here is a sample:

TMyComponent unit:
 
unit uCompX;

interface

uses Classes, Controls, SysUtils;

type
  TMyComponent = class(TComponent)
  private
    fVle: TStrings;
    procedure SetVLE(const Value: TStrings);
    function GetVle: TStrings;
  protected
  public
    constructor Create(aOwner: TComponent); override;
    destructor Destroy; override;
  published
    property VLE: TStrings read GetVle write SetVLE;
  end;

implementation

{ TMyComponent }

constructor TMyComponent.Create(aOwner: TComponent);
begin
  inherited Create(aOwner);
  fVle := TStringList.Create;
end;

destructor TMyComponent.Destroy;
begin
  FreeAndNil(fVle);
  inherited Destroy;
end;

function TMyComponent.GetVle: TStrings;
begin
  Result := fVle;
end;

procedure TMyComponent.SetVLE(const Value: TStrings);
begin
  fVle.Assign(Value);
end;

end.

Open in new window


The property editor with ValueListEditor as component
 
unit uCompVLE;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Grids, ValEdit, Buttons, ExtCtrls, DesignIntf, DesignEditors;

type
  TfrmValueListEditor = class(TForm)
    pnlOptions: TPanel;
    btnCancel: TBitBtn;
    btnOk: TBitBtn;
    vleItems: TValueListEditor;
  end;

  TValueListPropertyEditor = class(TClassProperty)
  public
    function GetAttributes: TPropertyAttributes; override;
    procedure Edit; override;
  end;

var
  frmValueListEditor: TfrmValueListEditor;

implementation

uses uCompX;

{$R *.dfm}

{ TValueListPropertyEditor }

procedure TValueListPropertyEditor.Edit;
var
 frm: TfrmValueListEditor;
 temp: string;
begin
  Temp := TMyComponent(GetComponent(0)).VLE.Text;
  frm := TfrmValueListEditor.Create(nil);
  try
    frm.vleItems.Strings.Text := Temp;
    if frm.ShowModal = mrOk then
    begin
      temp := frm.vleItems.Strings.Text;
      TMyComponent(GetComponent(0)).VLE.Text := Temp;
    end;
  finally
    FreeAndNil(frm);
  end;
end;

function TValueListPropertyEditor.GetAttributes: TPropertyAttributes;
begin
  Result := inherited GetAttributes + [paDialog, paReadOnly] - [paSubProperties];
end;

end.

Open in new window

and dfm:
 
object frmValueListEditor: TfrmValueListEditor
  Left = 331
  Top = 276
  Caption = 'Value List Property Editor'
  ClientHeight = 302
  ClientWidth = 694
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object pnlOptions: TPanel
    Left = 0
    Top = 261
    Width = 694
    Height = 41
    Align = alBottom
    TabOrder = 0
    DesignSize = (
      694
      41)
    object btnCancel: TBitBtn
      Left = 603
      Top = 8
      Width = 75
      Height = 25
      Anchors = [akTop, akRight]
      DoubleBuffered = True
      Kind = bkCancel
      ParentDoubleBuffered = False
      TabOrder = 0
    end
    object btnOk: TBitBtn
      Left = 522
      Top = 8
      Width = 75
      Height = 25
      Anchors = [akTop, akRight]
      DoubleBuffered = True
      Kind = bkOK
      ParentDoubleBuffered = False
      TabOrder = 1
    end
  end
  object vleItems: TValueListEditor
    Left = 0
    Top = 0
    Width = 694
    Height = 261
    Align = alClient
    KeyOptions = [keyEdit, keyAdd, keyDelete, keyUnique]
    TabOrder = 1
    ColWidths = (
      150
      538)
  end
end

Open in new window


and the registration unit
 
unit uRegComp;

interface

procedure Register;

implementation

uses uCompX, uCompVle, Classes, DesignWindows, DesignIntf, DesignEditors;

procedure Register;
begin
  RegisterComponents('MyComponents', [TMyComponent]);
  RegisterPropertyEditor(TypeInfo(TStrings), TMyComponent, 'VLE', TValueListPropertyEditor);
end;

end.

Open in new window


and the whole package code:
 
package pkgVle;

{$R *.res}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES OFF}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$IMPLICITBUILD ON}

requires
  rtl,
  designide;

contains
  uCompX in 'uCompX.pas',
  uRegComp in 'uRegComp.pas',
  uCompVLE in 'uCompVLE.pas' {frmValueListEditor};

end.

Open in new window


it's only for the first selected component
0
 
fischermxAuthor Commented:
The solution is to create my own property editor that calls the TValueListEditor.

  TPropsProperty = class(TPropertyEditor)
  public
    function GetAttributes: TPropertyAttributes; override;
    procedure Edit; override;
    function GetValue: string; override;
  end;

Register this property editor:
  RegisterPropertyEditor( TypeInfo(TStrings), TMyComponent, 'Props',  TPropsEditor);

And the most important.

Override the Edit method of the TPropertyEditor descendant, and from there, create a TValueListEditor on the fly, by creating a form first, and then having it as parent.

Or... to design a normal Form put the TValueListEditor, the buttons, etc and create it from the Edit method.
0
 
fischermxAuthor Commented:
I knew how to do a property editor.
My problem was that I thought the TValueListEditor could be used as property editor in a more "automagic" way... and it's not.

0
 
fischermxAuthor Commented:
oops...... we were typing at the same time!! :( sorry
Let me see if I can rollback the request I did.
0
 
fischermxAuthor Commented:
Moderator:

Please, disregard my request as accept my comment as solution.
The user Geert_Gruwez was posting a very good and definitive solution at the same time.

Accept Geert_Gruwez solution and award full points with Grade "A".

0
 
Ephraim WangoyaCommented:

The author requested full points to be assigned to Geert with A Grade
0
 
Geert GruwezOracle dbaCommented:
you can do the poinx yourself now ... :)
0
 
fischermxAuthor Commented:
Thank you!
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now