2011-08-05 60 views
4

我执行WPF列表框之间的拖放,我希望能够在它被丢弃,而不是列表的末尾位置插入到集合中。WPF列表框IndexFromPoint

有谁知道一个解决方案,就是类似的WinForms ListBox中IndexFromPoint功能?

+0

这可能有所帮助:http://msdn.microsoft.com/en-us/library/ms752097.aspx#Y4200 –

回答

6

我结束了使用的DragDropEvent.GetPosition,VisualTreeHelper.GetDescendantBounds和Rect.Contains组合得到这个工作。这是我想出的:

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; 
    } 
} 

该代码驻留在ListBox Drop事件中。 e对象是传递给Drop事件的DragEventArgs对象。

为IsMouseOverTarget的实现是:

private static bool IsMouseOverTarget(Visual target, Point point) 
{ 
    var bounds = VisualTreeHelper.GetDescendantBounds(target); 
    return bounds.Contains(point); 
} 
+0

谢谢,先生!你让我今天很开心! – Steffen

3

您可以使用

itemsControl.InputHitTest(position). 

从那里去了可视化树,直到你遇到正确的ItemContainer(用于列表框,你会发现一个ListBoxItem,等...)

然后调用

itemsControl.ItemContainerGenerator.IndexFromContainer(listBoxItem) 

以获取插入索引。

+0

我只是试过这个,但也许我做错了什么。我看到发生的事情是InputHitTest返回给我一个TextBlock,它不允许我比较ListBoxItem。我假设,因为我的ListBox绑定到一个ObservableCollection的字符串。 – Josh

+0

不,请继续从textblock(递归地,即将该调用的结果传回该方法)调用VisualTreeHelper.GetParent(dependencyObject),直到您点击一个listboxitem。 –

+0

啊啊。为了避免递归,我想我会坚持使用下面的内容。我会投你的答案,因为它会起作用。 – Josh

1

这是我要做的事 - 没有戏剧与迭代列表等

//Get the position 
var currp = e.GetPosition(dgrid); 
//Get whats under that position 
var elem=dgrid.InputHitTest(currp); 
//Your ListView or DataGrid will have set the DataContext to your bound item 
if (elem is FrameworkElement && (elem as FrameworkElement).DataContext != null) 
{ 
    var target=dgrid.ItemContainerGenerator.ContainerFromItem((elem as FrameworkElement).DataContext) 
} 

这是要点 - 然后你可以使用ItemContainerGenerator.ContainerFromItem或/和IndexFromContainer获取索引 - 但我怀疑最想要使用项目