检测发生rightTapped事件的ListViewitem

时间:2013-12-18 21:02:53

标签: c# windows-runtime windows-store-apps

如果没有ListItem事件和相关来源,有没有办法让RightTappedRoutedEventArgs e来自SelectionChanged,因为此ListViewSelectionMode="none"。如果使用SelectionMode="none"无法做到这一点,是否可以使用其他选择类型,但仍然没有选择更改事件?

下面的项目xaml模板。

<ListView.ItemTemplate>
 <DataTemplate>
   <Grid Height="56" Width="300">
     <Image .../>
    <TextBlock .../>
   </Grid>
 </DataTemplate>
</ListView.ItemTemplate>

由于一些实验,我已经将ListView(具有当前未使用的功能)子类化,并且还使用RightTapped子类化了ListViewItem。也许有办法将this附加到活动中?将此作为选择结果存储在子类ListView中是一种不好的行为。

2 个答案:

答案 0 :(得分:1)

我意识到这是一个老问题,但是本周我偶然发现了这个问题。

在很多情况下,Crea7or的回答是正确的(一旦您展示了DataContext,就可以经常使用ContainerFromItem来获取ListViewItem),但是它在两种重要情况下也不起作用:

  • 键盘激活(Shift + F10和键盘上的“上下文菜单”按钮都将触发RightTapped事件since Windows 8.1
  • 如果您的ItemTemplate包含其他具有自己的DataContexts的元素,例如<Button>(甚至是隐式的)。

对于第一种情况(由键盘激活的 ),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的更可靠的方法。

答案 1 :(得分:0)

<ListView.ItemTemplate>
 <DataTemplate>
   <Grid Height="56" Width="300" IsHitTestVisible="False">
...

所以现在我始终将Border视为原始发件人。之前是TextBoxImage

然后在:

private void itemsListBoxRightTapped( object sender, RightTappedRoutedEventArgs e )
{
  Border clickBorder = e.OriginalSource as Border;
  if ( clickBorder != null )
  {
     MyItemType selectedItem = clickBorder.DataContext as MyItemType;
   ...

中提琴!点按项目。

现在正确完成了ListView的上下文菜单;)

更新:Windows通用应用有[{1}}而不是ListViewItemPresenter