我知道这是一个老问题,但我这周偶然发现了这个问题。
Crea7or 的回答在很多情况下都是正确的(一旦你有他们演示的 DataContext,你通常可以使用ContainerFromItem 来获取ListViewItem),但它在两个重要的场景中也不起作用:
对于第一种情况(由键盘激活),e.OriginalSource 没有 DataContext。但是,e.OriginalSource 已经是 ListViewItem!这样你就完成了!
但是,对于第二种情况(包含具有自己的 DataContexts 的元素),查看 DataContext 可能会为您提供一个孩子的 DataContext,而不是您想要的!
查找 ListViewItem 的最可靠方法就是沿着树向上走(改编自 mm8's answer 类似的问题):
private static T FindParent<T>(DependencyObject dependencyObject) where T : DependencyObject
{
var parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null) return null;
var parentT = parent as T;
return parentT ?? FindParent<T>(parent);
}
// ... in your code ...
ListViewItem lvi = e.OriginalSource as ListViewItem;
if (lvi == null)
{
lvi = FindParent<ListViewItem>(e.OriginalSource as DependencyObject);
}
如果您确信第二种情况不适用,您可以采用更简单的方法从任意事件中获取 ListViewItem:
var listViewItem = e.OriginalSource as ListViewItem;
if (listViewItem == null)
{
var dataContext = (e.OriginalSource as FrameworkElement).DataContext;
listViewItem = (sender as ListView).ContainerFromItem(dataContext) as ListViewItem;
}
然而,这个问题的原始答案实际上是想要获取实际对象支持 ListViewItem。
要稳健地找到表示的实际对象——在处理上述所有其他场景时,获取 ListViewItem 并使用ItemsControl.ItemFromContainer 方法获取实际对象:
private void itemsListBoxRightTapped( object sender, RightTappedRoutedEventArgs e )
{
MyItemType item;
ListViewItem lvi = e.OriginalSource as ListViewItem;
if (listViewItem == null)
{
// Use earlier definition for FindParent.
listViewItem = FindParent<ListViewItem>(e.OriginalSource as DependencyObject);
}
item = (sender as ListView).ItemFromContainer(listViewItem) as MyItemType;
// We have the item!
}
ItemsControl 有一些其他非常好的辅助方法,例如IndexFromContainer。
编辑历史记录:
- 添加了关于如何从任意事件中获取 ListViewItem 的说明。
- 为获取 ListViewItems 添加了更强大的方法。