Logrus
Topic Author
Posts: 54
Joined: 22 Jul 2015, 12:16

TreeViewItem DragDrop Adorner

01 Apr 2024, 13:38

Hi
How best to implement Adorner for TreeViewItem for insertBefore, insertAfter operations.
I have found several implementations.
What method do you use in Noesis.Studio?
 
User avatar
maherne
Site Admin
Posts: 42
Joined: 01 Jul 2022, 10:10

Re: TreeViewItem DragDrop Adorner

02 Apr 2024, 15:29

For Studio we have a Behavior, called NavigatorDragBehavior, which creates and manages an Adorner, NavigatorDragAdorner. NavigatorDragBehavior handles the logic, while NavigatorDragAdorner renders the details in the view.

NavigatorDragBehavior is attached to the TreeView in XAML. In NavigatorDragBehavior::OnAttached we hook delegates into the TreeView's Loaded, PreviewDragOver, PreviewDragLeave, and PreviewDrop routed events (the TreeView is accessed in the Behavior using GetAssociatedObject).

The Loaded event is used to find the root element in the document, get the AdornerLayer for it using AdornerLayer::GetAdornerLayer, create a new instance of NavigatorDragAdorner, and add it to this layer.

The PreviewDragOver event is used to update NavigatorDragAdorner with a target and insert position, allowing it to render these details:

We use VisualTreeHelper::HitTest on the associated TreeView to find a target, and traverse through target parent(s) to find the TreeViewItem.
Point navMousePos = Mouse::GetPosition(owner);
HitTestResult hit = VisualTreeHelper::HitTest(owner, navMousePos);
FrameworkElement* target = DynamicCast<FrameworkElement*>(hit.visualHit);

while (target->GetParentOrTemplatedParent() != nullptr)
{
  target = target->GetParentOrTemplatedParent();
}
If target is a TreeViewItem, we calculate the insert position (before, over, after) based on position of the mouse over the target element.

We then call NavigatorDragAdorner::SetTarget which takes the target element, and it's insert position (before, over, after). If the target is not valid (null or not a TreeViewItem) then we call NavigatorDragAdorner::SetTarget with a nullptr target element, preventing the adorner from rendering any drag details.

The PreviewDragLeave event simply clears the NavigatorDragAdorner target by calling NavigatorDragAdorner::SetTarget with a nullptr target element, preventing the adorner from rendering any drag details.

The PreviewDrop event can handle the insert logic for the TreeView, using the same VisualTreeHelper::HitTest logic to find the target element and position, as is used in PreviewDragOver. It should also clear the adorner's target. In our case this insertion logic is elsewhere, as it is part of another system.
 
Logrus
Topic Author
Posts: 54
Joined: 22 Jul 2015, 12:16

Re: TreeViewItem DragDrop Adorner

02 Apr 2024, 16:13

Great
Thanks for the detailed answer.

Who is online

Users browsing this forum: Semrush [Bot] and 9 guests