First, obviously you need to register a mouse button event hander in your control initialization. In this case, I'm using a double-click event:
MyListView.MouseDoubleClick += new MouseButtonEventHandler(MyListView_MouseDoubleClick);and then implement the event handler like such:void MyListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)What we are doing is walking up the visual tree starting at the element the generated the mouse event. We stop when we find a ListViewItem, which we can then use to get the corresponding data item. If all you want is the index of the item, use IndexFromContainer() instead.
{
DependencyObject dep = (DependencyObject)e.OriginalSource;
while ((dep != null) && !(dep is ListViewItem))
{
dep = VisualTreeHelper.GetParent(dep);
}
if (dep == null)
return;
MyDataItemType item = (MyDataItemType)MyListView.ItemContainerGenerator.ItemFromContainer(dep);
// Do something with the item...
}
I saw how to get row or item, but how can I get column information from the mouse click position?
ReplyDeleteTry this and see how it works...
ReplyDeleteSystem.Data.DataRowView value = (System.Data.DataRowView)ListViewEmployeeDetails.SelectedValue;
MessageBox.Show(value.Row[0].ToString());
Thanks much, you just saved me some time figuring it out. Here is a VB version.
ReplyDeleteDim clickedToDoItem As ToDoItemInfo
Dim dep As DependencyObject = CType(e.OriginalSource, DependencyObject)
Do While dep IsNot Nothing AndAlso Not TypeOf (dep) Is ListViewItem
dep = VisualTreeHelper.GetParent(dep)
Loop
If dep Is Nothing Then
Return
Else
clickedToDoItem = CType(Me.lvToDo.ItemContainerGenerator.ItemFromContainer(dep), ToDoItemInfo)
End If
MessageBox.Show(String.Format("You clicked item: date={0},description={1}", clickedToDoItem.Due, clickedToDoItem.Description))
Thanks for the info. It worked great in my project and helped me solve two issues I was having. I really am starting to like WPF, but it is still taking a long time to figure it all out.
ReplyDeleteThis code fails if the OriginalSource is derived from FrameworkContentElemnt (e.g. anything in a FlowDocument, such as Document.Run). Unfortunately, VisualTreeHelper deals with Visual and FrameworkElement objects, but not FrameworkContentElement objects. 8-|
ReplyDeleteAs the last comment indicated, you need to handle ContentElement's differently. If you hit a content element then you should get the logical parent.
ReplyDeleteThanks a lot for this. Was searching around for ages and found yours to be the most concise method. Thanks
ReplyDeletehi
ReplyDeletegreat code tnx!
Using
ReplyDeleteMyDataItemType item = (MyDataItemType)((ListViewItem)dep).DataContext
instead of
MyDataItemType item = (MyDataItemType)MyListView.ItemContainerGenerator.ItemFromContainer(dep);
is a bit more straight forward but may only work, if data source binding is used for the list view.
That's overly complex.
ReplyDeleteWhy would you do that?
If you have a listview, just do
<ListView SelectedItem="TheSelectedItem" ... >
and in the setter for TheSelectedItem do what you want with it.
I'm assuming you mean to use a binding to TheSelectedItem, but anyway that wouldn't work in my particular case for at least two reasons:
ReplyDelete1. I'm using a multi-selected ListView (SelectionMode of Multiple), so SelectedItem is meaningless.
2. I only want to act in response to mouse double-clicks, not selection.
Responding to a selection is easy, but it isn't what I'm trying to do. In any case, if you want take action on a selection change, a better way to do that is to use the SelectionChanged event.
You can use this as well:
ReplyDeletehttp://social.msdn.microsoft.com/Forums/en-US/wpf/thread/681dea50-6bd2-4676-8161-14416386778d
Or..
ReplyDeleteprivate void appList_MouseDoubleClick(object sender, RoutedEventArgs e) {
ListViewItem app = (ListViewItem)appList.Items[appList.SelectedIndex];
MessageBox.Show("you selected: " + app.Content);
}
Great post!
ReplyDeleteVery Good post!
ReplyDeleteI'm not sure if it would work in your case, Mike, but this worked for me:
ReplyDeleteprivate void ListViewItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
ListViewItem listViewItemSender = sender as ListViewItem;
MyBusinessObject doubleClickedBO = myListView.ItemContainerGenerator.ItemFromContainer(listViewItemSender) as MyBusinessObject;
}
TY - helped my project
ReplyDeleteNice dude! That worked perfectly. :)
ReplyDeleteI am trying to learn WPF and I had been struggling with this for days!
Thanks!
No one is having a problem with the error "expression of type 'System.Windows.DependencyObject' can never be of type 'System.Windows.Forms.ListViewItem'"??? I'm not sure what I'm doing wrong here...
ReplyDeleteThank you for this post!
ReplyDelete