简体   繁体   English

检测发生 rightTapped 事件的 ListViewitem

[英]Detect ListViewitem where rightTapped event happened

Is there any way to get the ListItem from RightTappedRoutedEventArgs e without SelectionChanged event and related sources because this ListView have SelectionMode="none" .有没有办法从RightTappedRoutedEventArgs e获取ListItem而没有SelectionChanged事件和相关来源,因为这个ListViewSelectionMode="none" If this is not possible with SelectionMode="none" , will it be available with other selection types, but still without selection change event?如果使用SelectionMode="none"无法做到这一点,那么它是否适用于其他选择类型,但仍然没有选择更改事件?

Item xaml template below.下面的项目 xaml 模板。

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

Due to some experiments, I have subclassed ListView (with currently unused functionality) and also subclassed ListViewItem with handling RightTapped.由于一些实验,我已经将 ListView 子类化(具有当前未使用的功能),并且还使用处理 RightTapped 子类化了 ListViewItem。 Maybe there is any way to attach this to event?也许有什么办法可以连接this给事件? Storing this as selection result in subclassed ListView is a not good behavior I think.我认为将其作为选择结果存储在子类 ListView 中是一种不好的行为。

I realize this is an old question, but I stumbled upon it this week.我意识到这是一个老问题,但本周我偶然发现了它。

Crea7or's answer is correct in many cases (once you have the DataContext as they demonstrate, you can often use ContainerFromItem to get the ListViewItem ), but it also does not work in two important scenarios: Crea7or 的答案在许多情况下是正确的(一旦您拥有了他们演示的 DataContext,您通常可以使用ContainerFromItem来获取ListViewItem ),但它在两个重要场景中也不起作用:

  • keyboard activation (Shift+F10 and the "context menu" button on keyboards will both trigger a RightTapped event since Windows 8.1 )键盘激活( 自 Windows 8.1 起, Shift+F10 和键盘上的“上下文菜单”按钮都将触发 RightTapped 事件)
  • if your ItemTemplate contains other elements with their own DataContext s , like a <Button> (even implicit).如果您的ItemTemplate包含其他具有自己DataContext元素,例如<Button> (甚至是隐式的)。

For the first scenario ( activated by keyboard ), e.OriginalSource has no DataContext.对于第一个场景(由键盘激活), e.OriginalSource没有 DataContext。 However, e.OriginalSource is already the ListViewItem !但是, e.OriginalSource已经是ListViewItem So you're done!所以你完成了!

However, for the second scenario ( contains elements with their own DataContexts ), looking at the DataContext might get you a DataContext for a child—not what you want!但是,对于第二个场景(包含具有自己的 DataContext 的元素),查看 DataContext 可能会为您提供一个孩子的 DataContext——而不是您想要的!

The most robust way of looking up the ListViewItem is simply to walk up the tree (adapted from mm8's answer to a similar question):查找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);
}

If you are confident that the second scenario does not apply, you can take a simpler approach to get the ListViewItem from an arbitrary event:如果您确信第二种情况不适用,则可以采用更简单的方法从任意事件中获取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;
}

However, the original answer to this question actually wanted to grab the actual object backing the ListViewItem.然而,这个问题的原始答案实际上是想获取支持ListViewItem 的实际对象。

To find the actual object being represented robustly—while handling all the additional scenarios outlined above, fetch the ListViewItem and use the ItemsControl.ItemFromContainer method to get the actual object:要找到可靠表示实际对象——在处理上述所有附加场景的同时,获取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 has some other very nice helper methods, like IndexFromContainer . ItemsControl有一些其他非常好的辅助方法,例如IndexFromContainer


Edit history:编辑历史:

  • added clarification on how to get ListViewItem s from an arbitrary event.添加了有关如何从任意事件获取ListViewItem的说明。
  • added more robust method for fetching ListViewItems.添加了更强大的方法来获取 ListViewItems。
<ListView.ItemTemplate>
 <DataTemplate>
   <Grid Height="56" Width="300" IsHitTestVisible="False">
...

So now I see always Border as original sender.所以现在我总是将Border视为原始发件人。 It was TextBox or Image before.之前是TextBoxImage

then at:然后在:

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

viola!中提琴! Tapped item.点击的项目。

Now correct context menu for ListView is done ;)现在完成了 ListView 的正确上下文菜单;)

Update : Windows Universal apps have ListViewItemPresenter instead of Border .更新:Windows 通用应用程序具有ListViewItemPresenter而不是Border

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM