I have a custom control. It has a published property of type TOwnedCollection, which of course contains several instances of TCollectionItem (inherited to my own implementation). Let's call them TMyComponent, TMyCollection, and TMyCollectionItem.
Within TMyCollectionItem, I have a TPersistent property (let's call it MyProp: TMyProp), which also has a corresponding design-time editor installed into the IDE. All this works just fine, so when you're editing the collection, select a collection item, you can click the little button in the object inspector to invoke the property editor. All of this works fine.
What I would like to add is the ability to double-click the item within the collection editor to also invoke that very same property editor. However, I cannot find decent information how to do this. ChatGPT gave me code that simply didn't compile, probably because it was for much older versions of Delphi.
How do I implement the ability to double-click a TMyCollectionItem to invoke the property editor for TMyCollectionItem.MyProp?
NOTE: Looking into the source of ColnEdit.pas (for this collection editor), I see the TListView implements OnClick, but not OnDblClick, and so I'm questioning whether it's even possible to do what I want without rolling out my own collection editor.
The IDE's default Collection Editor does not natively support the feature you are looking for. As you noted:
The default Collection Editor simply does not implement any logic when a
TListViewitem is double-clicked on.(BTW, it is not the
TListVew.OnClickevent that updates the Object Inspector, it is theTListVew.OnChangeevent that does. That is the event that fires when ListView items are selected.)However, all is not lost! There IS a way you can access the
TListViewof the default Collection Editor and assign your ownOnDblClickevent handler to it:Derive a new class from
ColnEdit.TCollectionEditor, and have it assign anOnDblClickhandler to the inheritedTListView.Derive a new class from
ColnEdit.TCollectionPropertyand override its virtualGetEditorClass()method to return yourTCollectionEditor-derived class type.Register your
TCollectionProperty-derived class withDesignIntf.RegisterPropertyEditor()to override the default collection editor for yourTMyCollectionclass.Your derived Collection Editor can then invoke your
TMyPropproperty editor when needed by using theDesignEditors.GetComponentProperties()function:Use
DesignIntf.CreateSelectionList()to create a list andAdd()the appropriateTMyCollectionItemobject to it.Pass that list to
GetComponentProperties(), along with a callback that will receive anIPropertyEditorfor each property of theTMyCollectionItemobject.When the callback sees your
TMyPropproperty editor, it can call the editor'sEdit()method.For example:
That being said, I did test this approach and while it DOES work functionally, there is a slight visual side effect - in 10.2.1 and later, the IDE's theming feature will no longer apply to your Collection Editor window when it is shown. So, for instance, if you use a Dark theme in the IDE, the Collection Editor will not appear Dark anymore.
To fix this, you need to use the
IOTAIDEThemingServicesinterface in the OpenTools API to register yourTCollectionEditor-derived class so the IDE will theme it:Using IDE Styles in Third-Party Plugins
David Hoyle has also written an article on this topic:
Theming OTA Forms
For example:
Despite Embarcadero's documentation saying the following (emphasis is mine):
I find that if
RegisterFormClass()is not called again beforeApplyStyle()after a Theme change, thenApplyStyle()DOES NOT apply the new theme correctly! As-if the IDE lost the previous Form class registration during the Theme change (IDE bug? I have reported it: RSP-43972). CallingRegisterFormClass()before each call toApplyStyle()works.I also noticed that the default
TCollectionEditordoes not react to IDE Theme changes at all (definitely an IDE bug, which I have reported: RSP-43971).