Detecting Double Click Events on the WPF DataGrid
Either I missed the obvious solution, or there is indeed no simple way to catch double click events on a given row of Microsoft’s WPF DataGrid.
This snippet here fires the event whenever the grid is clicked – it doesn’t matter whether the user double-clicks into an empty area (no rows) or a row:
<!-- fires even if the user does not click a given row --> <dg:DataGrid dg:DataGridRow.MouseDoubleClick="OnDoubleClick" />
As a result, I reverted to a workaround by searching the Visual Tree of the event source for an instance of type DataGridRow. In order to find the ancestor item, I used a snippet I posted here a while ago. Here’s the full code:
XAML:
<!-- just register a listener on the grid --> <dg:DataGrid MouseDoubleClick="OnDoubleClick" />
Code-Behind:
/// <summary> /// Handles double-clicks on datagrid rows. /// </summary> private void OnDoubleClick(object sender, MouseButtonEventArgs e) { //search the object hierarchy for a datagrid row DependencyObject source = (DependencyObject) e.OriginalSource; var row = UIHelpers.TryFindParent<DataGridRow>(source); //the user did not click on a row if (row == null) return; //[insert great code here...] e.Handled = true; }
UIHelper class providing the TryFindParent method:
(Snippet updated: 2009.09.14)
/// <summary> /// Finds a parent of a given item on the visual tree. /// </summary> /// <typeparam name="T">The type of the queried item.</typeparam> /// <param name="child">A direct or indirect child of the /// queried item.</param> /// <returns>The first parent item that matches the submitted /// type parameter. If not matching item can be found, a null /// reference is being returned.</returns> public static T TryFindParent<T>(this DependencyObject child) where T : DependencyObject { //get parent item DependencyObject parentObject = GetParentObject(child); //we've reached the end of the tree if (parentObject == null) return null; //check if the parent matches the type we're looking for T parent = parentObject as T; if (parent != null) { return parent; } else { //use recursion to proceed with next level return TryFindParent<T>(parentObject); } } /// <summary> /// This method is an alternative to WPF's /// <see cref="VisualTreeHelper.GetParent"/> method, which also /// supports content elements. Keep in mind that for content element, /// this method falls back to the logical tree of the element! /// </summary> /// <param name="child">The item to be processed.</param> /// <returns>The submitted item's parent, if available. Otherwise /// null.</returns> public static DependencyObject GetParentObject(this DependencyObject child) { if (child == null) return null; //handle content elements separately ContentElement contentElement = child as ContentElement; if (contentElement != null) { DependencyObject parent = ContentOperations.GetParent(contentElement); if (parent != null) return parent; FrameworkContentElement fce = contentElement as FrameworkContentElement; return fce != null ? fce.Parent : null; } //also try searching for parent in framework elements (such as DockPanel, etc) FrameworkElement frameworkElement = child as FrameworkElement; if (frameworkElement != null) { DependencyObject parent = frameworkElement.Parent; if (parent != null) return parent; } //if it's not a ContentElement/FrameworkElement, rely on VisualTreeHelper return VisualTreeHelper.GetParent(child); }
Enjoy 🙂