I am performing a drag drop between WPF ListBoxes and I would like to be able to insert into the collection at the position it is dropped rather than the end of the list.
Does anyone know of a solution that is similar to the WinForms ListBox IndexFromPoint function?
I ended up getting this work by using a combination of DragDropEvent.GetPosition, VisualTreeHelper.GetDescendantBounds and Rect.Contains. Here's what I came up with:
int index = -1;
for (int i = 0; i < collection.Count; i++)
{
var lbi = listBox.ItemContainerGenerator.ContainerFromIndex(i) as ListBoxItem;
if (lbi == null) continue;
if (IsMouseOverTarget(lbi, e.GetPosition((IInputElement)lbi)))
{
index = i;
break;
}
}
The code resides in the ListBox Drop event. The e object is the DragEventArgs object passed into the Drop event.
The implementation for IsMouseOverTarget is:
private static bool IsMouseOverTarget(Visual target, Point point)
{
var bounds = VisualTreeHelper.GetDescendantBounds(target);
return bounds.Contains(point);
}
You can use
itemsControl.InputHitTest(position).
Go up the visual tree from there until you hit the correct ItemContainer (for ListBox you would find ListBoxItem, etc....)
Then call
itemsControl.ItemContainerGenerator.IndexFromContainer(listBoxItem)
to get the index for insertion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With