C# 如何在没有SelectedIndex或类似内容的情况下获取列表框项目的索引(在PreviewMouseDown中,尚未“选择”任何内容)
如何实现下面的C# 如何在没有SelectedIndex或类似内容的情况下获取列表框项目的索引(在PreviewMouseDown中,尚未“选择”任何内容),c#,wpf,listbox,visualtreehelper,C#,Wpf,Listbox,Visualtreehelper,如何实现下面的GetListBoxItemIndex函数来获取我单击的项目的索引?我尝试使用VisualTreeHelper,但没有成功(这意味着,VisualTreeHelper显然有效,但我在树搜索中没有任何进展…) private void MyListBox\u OnPreviewMouseDown(对象发送器,鼠标按钮ventargs e){ var listBox=发送方作为列表框; var src=e.OriginalSource作为DependencyObject; if(src
GetListBoxItemIndex
函数来获取我单击的项目的索引?我尝试使用VisualTreeHelper
,但没有成功(这意味着,VisualTreeHelper
显然有效,但我在树搜索中没有任何进展…)
private void MyListBox\u OnPreviewMouseDown(对象发送器,鼠标按钮ventargs e){
var listBox=发送方作为列表框;
var src=e.OriginalSource作为DependencyObject;
if(src==null | | listBox==null)返回;
var i=GetListBoxItemIndex(listBox,src);
DragDrop.DoDragDrop(src,BoundCollection[i],DragDropEffects.Copy);
//边界集合定义为:
//可观测集合边界集合
}
请注意,在此状态下尚未选择任何内容,因为这是一个
PreviewMouseDown
事件以下代码将帮助您解决问题,步骤在注释中
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;
}
private void ListBox\u OnPreviewMouseDown(对象发送器,鼠标按钮ventargs e)
{
//您可以检查哪个鼠标按钮、其状态或使用正确的事件。
//获取鼠标当前所在的元素
var uie=ListBox.InputHitTest(Mouse.GetPosition(this.ListBox));
if(uie==null)
返回;
//导航到其ListBoxItem容器
var listBoxItem=FindParent((FrameworkElement)uie);
//如果单击不是在listBoxItem上
如果(listBoxItem==null)
返回;
//这是索引
int index=this.ListBox.ItemContainerGenerator.IndexFromContainer(listBoxItem);
Show(index.ToString());
}
公共静态T FindParent(FrameworkElement子级),其中T:DependencyObject
{
T parent=null;
var currentParent=VisualTreeHelper.GetParent(子级);
while(currentParent!=null)
{
//检查当前父级
如果(当前父项为T)
{
父项=(T)当前父项;
打破
}
//找到下一个家长
currentParent=VisualTreeHelper.GetParent(currentParent);
}
返回父母;
}
更新
您需要的是单击的数据项的索引。获取容器后,只有通过DataContext
获取与其关联的数据项并在绑定集合中查找其索引,才能获取索引。ItemContainerGenerator
已经为您完成了这项工作
在代码中,您假设ListBoxItem
索引与绑定集合中的数据项的索引相同,只有禁用了Virtualization
时才是如此。如果启用,则仅实例化可见区域中项目的容器。例如,如果绑定集合中有1000个数据项,并且已滚动到第50个数据项,那么从理论上讲,索引0处的ListBoxItem
将绑定到第50个数据项,这证明您的假设是错误的
我在前面理论上说过,因为当
虚拟化
开启时,会在滚动区域的顶部和底部创建一些隐藏容器,以便键盘导航正常工作。以下代码将帮助您解决问题,步骤在注释中
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;
}
private void ListBox\u OnPreviewMouseDown(对象发送器,鼠标按钮ventargs e)
{
//您可以检查哪个鼠标按钮、其状态或使用正确的事件。
//获取鼠标当前所在的元素
var uie=ListBox.InputHitTest(Mouse.GetPosition(this.ListBox));
if(uie==null)
返回;
//导航到其ListBoxItem容器
var listBoxItem=FindParent((FrameworkElement)uie);
//如果单击不是在listBoxItem上
如果(listBoxItem==null)
返回;
//这是索引
int index=this.ListBox.ItemContainerGenerator.IndexFromContainer(listBoxItem);
Show(index.ToString());
}
公共静态T FindParent(FrameworkElement子级),其中T:DependencyObject
{
T parent=null;
var currentParent=VisualTreeHelper.GetParent(子级);
while(currentParent!=null)
{
//检查当前父级
如果(当前父项为T)
{
父项=(T)当前父项;
打破
}
//找到下一个家长
currentParent=VisualTreeHelper.GetParent(currentParent);
}
返回父母;
}
更新
您需要的是单击的数据项的索引。获取容器后,只有通过DataContext
获取与其关联的数据项并在绑定集合中查找其索引,才能获取索引。ItemContainerGenerator
已经为您完成了这项工作
在代码中,您假设ListBoxItem
索引与绑定集合中的数据项的索引相同,只有禁用了Virtualization
时才是如此。如果启用,则仅实例化可见区域中项目的容器。例如,如果绑定集合中有1000个数据项,并且已滚动到第50个数据项,那么从理论上讲,索引0处的ListBoxItem
将绑定到第50个数据项,这证明您的假设是错误的
我在前面理论上说过,因为当
虚拟化
开启时,会在滚动区域的顶部和底部创建一些隐藏容器,以便键盘导航正常工作。以下代码将帮助您解决问题,步骤在注释中
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;
}
private void ListBox\u OnPreviewMouseDown(对象发送器,鼠标按钮ventargs e)
{
//您可以检查哪个鼠标按钮、其状态或使用正确的事件。
//获取鼠标当前所在的元素
var uie=ListBox.InputHit