Reputation: 2089
I have created a new designtime component, which contains a published property Handler
of type TComponent
and registered it into the Tool Palette.
When i place a component of this type on my form, the property editor of the IDE shows me the property 'Handler' with a dropdown box that allows me to set this property at design time. The dropbox shows all available TComponents on the current form.
How can I restrict the list of components that is shown here (design time) to components of a certain type or with a certain property? i.e. Components that implement a certain (set of) interfaces.
I know that you can also use interface-properties, but also encountered several posts on the internet stating that this is very unstable and raises all kinds of problems.
Is there a method I can call for each of the proposed components where I can determine if they should appear in the list at design time?
Addition after the answer of @David:
Now that I've learned that TComponentProperty is what i was looking for, I also found a related question here: How to modify TComponentProperty to show only particular items on drop down list?
Upvotes: 0
Views: 352
Reputation: 612954
TComponentProperty
.GetValues
method to apply your filter.TComponentProperty
as the property editor for your property.Here is a very simple example:
Component
unit uComponent;
interface
uses
System.Classes;
type
TMyComponent = class(TComponent)
private
FRef: TComponent;
published
property Ref: TComponent read FRef write FRef;
end;
implementation
end.
Registration
unit uRegister;
interface
uses
System.SysUtils, System.Classes, DesignIntf, DesignEditors, uComponent;
procedure Register;
implementation
type
TRefEditor = class(TComponentProperty)
private
FGetValuesProc: TGetStrProc;
procedure FilteredGetValuesProc(const S: string);
public
procedure GetValues(Proc: TGetStrProc); override;
end;
procedure TRefEditor.FilteredGetValuesProc(const S: string);
begin
if S.StartsWith('A') then
FGetValuesProc(S);
end;
procedure TRefEditor.GetValues(Proc: TGetStrProc);
begin
FGetValuesProc := Proc;
try
inherited GetValues(FilteredGetValuesProc);
finally
FGetValuesProc := nil;
end;
end;
procedure Register;
begin
RegisterComponents('Test', [TMyComponent]);
RegisterPropertyEditor(TypeInfo(TComponent), nil, 'Ref', TRefEditor);
end;
end.
This rather useless property editor will only offer you components whose names begin with A
. Despite its complete lack of utility, this does illustrate the ability to filter that you desire. You'll likely want to call Designer.GetComponent(...)
passing a component name to obtain the component instance, and implement your filtering based on the type and state of that component instance.
Upvotes: 4
Reputation: 8331
As @TLama already pointed out you need to change the tpe of handler field/property.
Now in case if you want to ba able to assign specific type of component to this field/property then set this field type to the same type of that compomnent.
But if you want to be able to assign several different component types but not all components make sure that Handler field/property type is the type of the first common ancestor class/component of your desired components that you want to be able to assign to the Handler field/property.
Upvotes: -1