18

In an event handler for a Command for a DataGrid, I get DataGridCell in ExecutedRoutedEventArgs. However, I couldn't figure out how to get its associated DataGrid and DataGridRow. Your help is much appreciated.

newman
  • 6,841
  • 21
  • 79
  • 126

3 Answers3

15

You probably want to set some sort of RelativeSource binding that can get you the "parent grid/row" via a {RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, but your question got me thinking...

You could:

Use Reflection:

var gridCell = ....;
var parentRow = gridCell
         .GetType()
         .GetProperty("RowOwner", 
               BindingFlags.NonPublic | BindingFlags.Instance)
         .GetValue(null) as DataGridRow;

Use the VisualTreeHelper:

var gridCell = ...;
var parent = VisualTreeHelper.GetParent(gridCell);
while(parent != null && parent.GetType() != typeof(DataGridRow))
{
    parent = VisualTreeHelper.GetParent(parent);
}
JerKimball
  • 16,584
  • 3
  • 43
  • 55
5

Here is what I think is a complete answer...

    private void Copy(object sender, ExecutedRoutedEventArgs e)
    {
        DataGrid grid = GetParent<DataGrid>(e.OriginalSource as DependencyObject);
        DataGridRow row = GetParent<DataGridRow>(e.OriginalSource as DependencyObject);
    }

    private T GetParent<T>(DependencyObject d) where T:class
    {
        while (d != null && !(d is T))
        {
            d = VisualTreeHelper.GetParent(d);
        }
        return d as T;
    }
AQuirky
  • 4,691
  • 2
  • 32
  • 51
0

One way you could do is by passing one or both of the needed elements in as a CommandParameter:

<MouseBinding 
    MouseAction="LeftDoubleClick" 
    Command="cmd:CustomCommands.Open" 
    CommandParameter="{Binding ElementName=MyDataGrid}}" />

If you need both, you could add a multi-value converter that combines them into a Tuple (or leave it as an object[])

Then in your code-behind you can access it by using e.Parameter

Nathaniel
  • 83
  • 1
  • 7