问题
Is there any way to get the ListItem
from RightTappedRoutedEventArgs e
without SelectionChanged
event and related sources because this ListView
have SelectionMode="none"
. If this is not possible with SelectionMode="none"
, will it be available with other selection types, but still without selection change event?
Item xaml template below.
<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. Maybe there is any way to attach this
to event? Storing this as selection result in subclassed ListView is a not good behavior I think.
回答1:
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:
- keyboard activation (Shift+F10 and the "context menu" button on keyboards will both trigger a RightTapped event since Windows 8.1)
- if your
ItemTemplate
contains other elements with their own DataContexts, like a<Button>
(even implicit).
For the first scenario (activated by keyboard), e.OriginalSource
has no DataContext. However, e.OriginalSource
is already the 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!
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):
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:
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.
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:
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.
Edit history:
- added clarification on how to get ListViewItems from an arbitrary event.
- added more robust method for fetching ListViewItems.
回答2:
<ListView.ItemTemplate>
<DataTemplate>
<Grid Height="56" Width="300" IsHitTestVisible="False">
...
So now I see always Border
as original sender. It was TextBox
or Image
before.
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 ;)
Update: Windows Universal apps have ListViewItemPresenter
instead of Border
.
来源:https://stackoverflow.com/questions/20668323/detect-listviewitem-where-righttapped-event-happened