Prevent AutoExpand in a TreeListBox during dragover

Grids for WPF Forum

Posted 7 years ago by LONG Philippe
Version: 17.1.0652
Avatar

I use a TreeListBox and I have implemented a TreeListBoxItemAdapter to manage drag&drop.

Everything works fine, except for this :

During dragover, I would like to prevent the TreeListBox to auto-expand one node when I know that drop cannot happen in this node subtree.

I have tried :

- to set the TreeItemDropArea toTreeItemDropArea.After and the DragDropEffects to DragDropEffects.None in the OnDragOver method : no result

- to override the GetExpandability method : I find no way to manage node expandability only for drag operation

Is there a way to prevent a TreeListBox to auto-expand nodes during dragover ? 

Comments (15)

Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Philippe,

The code to expand nodes on drag is internal and there isn't a way to disable it at this time.  Are you asking for a flag on the TreeListBox control that would let you disable the hover-on-drag-to-expand feature for all nodes in that tree control?


Actipro Software Support

Posted 7 years ago by LONG Philippe
Avatar

Hi,

Thank you for responding so quickly !!

My need would be to be able to return something like TreeItemExpandability.NotOnDrag in the overrided GetExpandability method :

public override TreeItemExpandability GetExpandability(TreeListBox ownerControl, object item, int depth)
{
   if (item is OutlineViewNode) return TreeItemExpandability.NotOnDrag ;
   else return TreeItemExpandability.Auto;
}

 

or to disable the hover-on-drag-to-expand feature for only some kind of nodes in that tree control

Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Philippe,

Hmmm, I'm not sure if I like having that functionality be node-specific though since that seems like a usability issue.  Generally features like expanding by drag/hover should either be always expected or not at all.  Otherwise it's an inconsistent usability scenario and that isn't usually a good design.  Thoughts?


Actipro Software Support

Posted 7 years ago by LONG Philippe
Avatar

I think that it is useful to auto-expand a node during dragover only if you can expect to drop inside its subtree.
But I understand that it can be seen as a bug ...

Here is my use case :

I have a Tree with the following nodes :

  • Folder nodes
  • Each Folder node can contain Workflow nodes
  • Each Workflow node contains Outline nodes as a subtree

The user can drag and drop Workflow nodes on Folder nodes or on other Workflow nodes (before or after).

But he cannot drop a WorkflowNode inside the Outline of another Workflow.
So, I would like to avoid to auto-expand the Workflow nodes and the Outline nodes, but to keep the auto-expand on the Folder nodes.

Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

I had a thought... if you are aware of when you are in a drag scenario, you could handle the TreeListBox.ItemExpanding event and set e.Cancel based on what is being dragged.  That would allow you to selectively prevent the expand.

[Modified 7 years ago]


Actipro Software Support

Posted 7 years ago by LONG Philippe
Avatar

Yes, that's a good idea.

But, using TreeListBoxItemAdapter, I don't use DragDrop.DoDragDrop method to initialize drag scenario.

So, how can I know that drag scenario has been cancelled ?

Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hmm, true... it's a bit tough for us to properly track if a drag is occurring over any part of the control too.  What about adding this to the adapter:

/// <summary>
/// Notifies that a drag event hovered over a target item, returning whether the target item can be expanded when appropriate.
/// </summary>
/// <param name="e">The <see cref="DragEventArgs"/> with drag information.</param>
/// <param name="targetControl">The target control, over which the event occurred.</param>
/// <param name="targetItem">The target item.</param>
/// <returns>A <see cref="TreeItemExpandability"/> that indicates if the target item should expand.</returns>
public virtual TreeItemExpandability OnDragHover(DragEventArgs e, TreeListBox targetControl, object targetItem) {
	return TreeItemExpandability.Auto;
}

That way you'd be able to control whether the expand occurs based on which data is dragged and which target item.  Does that seem like a good solution to you?


Actipro Software Support

Posted 7 years ago by LONG Philippe
Avatar

Yes, it would be fine !!

Posted 7 years ago by LONG Philippe
Avatar

Another request : would it be possible to be notified when drag scenario is over (done or cancelled) ?

I display a visual during drag, and have to discard it when drag scenario is over.
It works fine using DragDrop.DoDragDrop, which is blocking.
So, I can discard when DoDragDrop returns.

Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

How are you currently creating the visual in the non-DoDragDrop scenario?


Actipro Software Support

Posted 7 years ago by LONG Philippe
Avatar

I override the TreeListBoxItemAdapter.InitializeDataObject method, where I create the visual (a small singleton window which follows the cursor).

If drop occurs anywhere in the application, the drop receiver discards the visual.
If drop is cancelled, the visual remains visible (not very pretty), and will be discarded by the next drag scenario starting.

Of course, it looks like a bug for the users.
Do you know a better way to do that ?

Answer - Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

We kick off a DragDrop.DoDragDrop call right after itemAdapter.InitializeDataObject is called.  This is the code:

// Use the adapter to initialize the data object
var dataObject = new DataObject();
var allowedEffects = itemAdapter.InitializeDataObject(this, dataObject, draggableItems);

// Start a drag
if ((allowedEffects != DragDropEffects.None) && (dataObject.GetFormats().Any()))
	DragDrop.DoDragDrop(this, dataObject, allowedEffects);

The (allowedEffects != DragDropEffects.None) portion of the 'if' wasn't in there before, but we are adding that for the 2017.2 version.  That way you could possibly kick off the DragDrop.DoDragDrop call right from within InitializeDataObject yourself and then return None to prevent our call from happening.  Effectively like:

// TODO: Initialize DataObject like normal here
DragDrop.DoDragDrop(sourceControl, dataObject, DragDropEffects.Move);
return DragDropEffects.None;

Think that will work?


Actipro Software Support

Posted 7 years ago by LONG Philippe
Avatar

I will install 2017.2 version and try your solution.

It seems fine !!

Thank you very much for your time!!

Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

We hope to get the 2017.2 version with those changes out in the next couple days unless an issue pops up.


Actipro Software Support

Posted 7 years ago by LONG Philippe
Avatar

Ok, I will check the news.

The latest build of this product (v24.1.1) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.