WPF ListBox IndexFromPoint

4

我正在WPF ListBoxes之间执行拖放操作,希望能在拖放的位置插入到集合中,而不是列表末尾。

有没有人知道类似于WinForms ListBox IndexFromPoint函数的解决方案?


这可能会有所帮助:http://msdn.microsoft.com/en-us/library/ms752097.aspx#Y4200 - agent-j
3个回答

7

我最终通过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的拖放事件中。e对象是传递到Drop事件中的DragEventArgs对象。

IsMouseOverTarget的实现如下:

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

谢谢你先生!你刚刚让我一天都很开心! - Steffen

3
您可以使用

标签


itemsControl.InputHitTest(position).

从那里开始往上遍历视觉树,直到找到正确的ItemContainer(对于ListBox,您将找到ListBoxItem等等...)。

然后调用

itemsControl.ItemContainerGenerator.IndexFromContainer(listBoxItem) 

获取插入的索引。


我刚刚尝试了一下,但可能做错了什么。我看到的是,InputHitTest 返回了一个 TextBlock,不允许我与 ListBoxItem 进行比较。我猜这是因为我的 ListBox 绑定到一个字符串的 ObservableCollection。 - Josh
不,继续从 TextBlock 中调用 VisualTreeHelper.GetParent(dependencyObject)(递归地,即将该调用的结果传回方法),直到找到 ListBoxItem。 - Double Down
啊,我明白了。为了避免递归,我想我会坚持使用下面的方法。不过我会投票支持你的答案,因为它也是可行的。 - Josh

3
这就是我处理的方式 - 无需对列表进行迭代等复杂操作。
//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来获取索引 - 不过我怀疑大多数人想使用Item。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接