检测发生右点击事件的列表视图项
本文关键字:列表 视图 事件 检测 | 更新日期: 2024-10-29 18:35:54
有没有办法在没有SelectionChanged
事件和相关来源的情况下从RightTappedRoutedEventArgs e
获取ListItem
,因为这ListView
SelectionMode="none"
.如果这在SelectionMode="none"
中无法实现,它是否可用于其他选择类型,但仍然没有选择更改事件?
下面的项 xaml 模板。
<ListView.ItemTemplate>
<DataTemplate>
<Grid Height="56" Width="300">
<Image .../>
<TextBlock .../>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
由于一些实验,我有子类化的ListView(具有当前未使用的功能)和子类化的ListViewItem,处理RightTapped。也许有什么方法可以将this
附加到事件中?我认为将其存储为子类化 ListView 中的选择结果是一种不好的行为。
我意识到这是一个老问题,但我本周偶然发现了它。
Crea7or的答案在许多情况下是正确的(一旦你有了他们所演示的DataContext,你通常可以使用ContainerFromItem
来获取ListViewItem
),但它在两个重要场景中也不起作用:
- 键盘激活(自 Windows 8.1 以来,Shift+F10 和键盘上的"上下文菜单"按钮都将触发 RightTap 事件)
- 如果您的
ItemTemplate
包含其他元素及其自己的DataContext
,例如<Button>
(甚至是隐式)。
对于第一种方案(由键盘激活),e.OriginalSource
没有数据上下文。但是,e.OriginalSource
已经是ListViewItem
了!大功告成!
但是,对于第二种情况(包含具有自己的 DataContext 的元素),查看 DataContext 可能会获得子项的数据上下文,而不是您想要的!
查找ListViewItem的最可靠方法是简单地走上树(改编自mm8对类似问题的回答):
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。
<小时 />编辑历史记录:
- 添加了有关如何从任意事件中获取列表视图项的说明。
- 添加了用于获取列表视图项的更强大的方法。
免责声明:我为Microsoft工作。
<ListView.ItemTemplate>
<DataTemplate>
<Grid Height="56" Width="300" IsHitTestVisible="False">
...
所以现在我看到总是Border
作为原始发件人。它以前是TextBox
或Image
的。
然后在:
private void itemsListBoxRightTapped( object sender, RightTappedRoutedEventArgs e )
{
Border clickBorder = e.OriginalSource as Border;
if ( clickBorder != null )
{
MyItemType selectedItem = clickBorder.DataContext as MyItemType;
...
中提琴!点击的项目。
现在,列表视图的正确上下文菜单已完成;)
更新:Windows 通用应用程序具有ListViewItemPresenter
而不是Border
。