I’ve been preparing to add some drag and drop support to MonkeyStyler, chiefly revolving around a couple of tree views. So, I set out to investigate drag/drop for a TTreeView. I figured the automatic drag/drop support wouldn’t be enough for me but I started with it to see how things worked, and what I’d need to adapt.

What I found wasn’t a pretty picture. The issues I found where:
* It takes two clicks to start a drag operation: one to select an item, another to pick it up ans start dragging QC 110783.
* You can’t drop onto another tree view if it the destination’s Selected = nil QC 110646.
* The built in code selects the wrong item when hovering or dropping unless the tree view’s Position is at (0,0) on the form QC 110721.
all of which make the built in support unusable.

And finally comes the enhancements I need to use for MonkeyStyler:
* The built in behaviour is to move a TTreeViewItem from one location to another but I also need to be able to manage the data structures behind the tree view.
* I want the ability to copy an item (and related back end data).
* I want to be able to move items other than TTreeViewItems (at present that means dragging an class from a palette and creating an instance of that class on dropping).

So I set about fixing the broken stuff and adding support for what I neeed.

The code attached to this post is a child component of TTreeView which reworks the default drag/drop behaviour to fix the issues above. Much of it is simply a cut/paste of the existing code with bug fixes added plus some rather nasty hacks to remove default behaviour and access a private field which is needed.

Behaviour of the new code is:
* Added an EnableDrag property which replaces the AllowDrag property. Set EnableDrag to True to switch on the dragging behaviour. Do not set both EnableDrag and AllowDrag to true. Indeed, don’t use AllowDrag at all, that will simply return you to the old two-clicks to drag behaviour.
* Added an OnDropItem event. If this is assigned then the event handler is solely responsible for handling any reparenting or other processing necessary when an item is dropped. The minimal code necessary to move an item would be (ignoring sanity checks):

TFMXObject(Item).Parent := TFMXObject(NewParent);

You can, of course, process the new item in any way you see fit.

The code at present is XE3 only. As and when I add XE2 support I’ll update the code and this post. The download includes a sample project with three tree views you can drag between. Uncomment the line to add an OnDropItem event handler to test that functionality.

Previous Comments

#1 from .(JavaScript must be enabled to view this email address) on January 15, 2013

Mike,
I’ve got to say I admire your perseverance with FireMonkey and QC!
Issues like this and some of the glitches I’ve found with standard components make me wonder if anyone can be really using FM2?
Thanks for sharing all your hard work anyway it’s much appreciated

#2 from .(JavaScript must be enabled to view this email address) on April 07, 2013

Thanks for this. It’s fixed some issues I’ve been having too. I’ve been trying to work out how to force the solenttreeview to take on the default style of the form - as it seems that it doesn’t inherit this form the panel.

Any ideas how one would go about doing this?

#3 from .(JavaScript must be enabled to view this email address) on April 18, 2013

It should work as-is, but you could try explicitly setting StyleLookup to ‘TreeViewStyle’.