以下代码将帮助您解决问题,步骤在评论中,
private void ListBox_OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
// you can check which mouse button, its state, or use the correct event.
// get the element the mouse is currently over
var uie = ListBox.InputHitTest(Mouse.GetPosition(this.ListBox));
if (uie == null)
return;
// navigate to its ListBoxItem container
var listBoxItem = FindParent<ListBoxItem>((FrameworkElement) uie);
// in case the click was not over a listBoxItem
if (listBoxItem == null)
return;
// here is the index
int index = this.ListBox.ItemContainerGenerator.IndexFromContainer(listBoxItem);
MessageBox.Show(index.ToString());
}
public static T FindParent<T>(FrameworkElement child) where T : DependencyObject
{
T parent = null;
var currentParent = VisualTreeHelper.GetParent(child);
while (currentParent != null)
{
// check the current parent
if (currentParent is T)
{
parent = (T)currentParent;
break;
}
// find the next parent
currentParent = VisualTreeHelper.GetParent(currentParent);
}
return parent;
}
更新
你想要的是你点击的数据项的索引。获得容器后,在通过 获取与其关联的数据项之前,您无法获得索引DataContext
,并在绑定集合中查找其索引。ItemContainerGenerator
已经为您做到了。
在您的代码中,您假设索引与绑定集合中的数据项的索引相同,这仅在关闭ListBoxItem
时才成立。Virtualization
如果它打开,则仅实例化可见区域中项目的容器。例如,如果您的绑定集合中有 1000 个数据项,并且您已经滚动到第 50 个数据项,那么现在,理论上,ListBoxItem
索引 0 绑定到第 50 个数据项,这证明您的假设是错误的。
前面说了理论上,因为开启时在滚动区域的顶部和底部会创建一些隐藏的容器Virtualization
,以便键盘导航正常工作。