46

I want to execute some code when a a selected row of the WPF DataGrid is double clicked. I know that the datagrid has a MouseDoubleClicked event and that it also has a row selected event but I don't see any event for "selected row double clicked" ...

Do you think it's possible to capture this event somehow ?

demonplus
  • 5,613
  • 12
  • 49
  • 68
MadSeb
  • 7,958
  • 21
  • 80
  • 121
  • 2
    If you use Caliburn.Micro and MVVM approach, there is a bit nicer way to accomplish this - [Getting row information after a doubleclick](http://stackoverflow.com/questions/9487084/getting-row-information-after-a-doubleclick). – Sevenate Jan 22 '14 at 10:07

7 Answers7

64

you can add the event handler in the ItemContainerStyle (which is the style applied to a row) :

<DataGrid ... >
    <DataGrid.ItemContainerStyle>
        <Style TargetType="DataGridRow">
            <EventSetter Event="MouseDoubleClick" Handler="Row_DoubleClick"/>
        </Style>
    </DataGrid.ItemContainerStyle>
    ...
</DataGrid>

Then, in the handler, you can check if the row is selected

private void Row_DoubleClick(object sender, MouseButtonEventArgs e)
{
    // execute some code
}
E-rich
  • 9,243
  • 11
  • 48
  • 79
Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
27

This question came up for me while looking for a solution and the answers didn't work, whether due to age or my own implementation. Either way, here is the solution that worked for me.

Add the MouseDoubleClick event to the DataGrid

        <DataGrid x:Name="DatagridMovie"
              Width="Auto"
              CanUserAddRows="False"
              CanUserDeleteRows="True"
              IsReadOnly="true"
              ItemsSource="{Binding}"
              MouseDoubleClick="Row_MouseDoubleClick">

and in the method

private void Row_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{                
    // Ensure row was clicked and not empty space
    var row = ItemsControl.ContainerFromElement((DataGrid)sender,
                                        e.OriginalSource as DependencyObject) as DataGridRow;

     if ( row == null ) return;

    … Stuff();
 }

So far I haven't noticed any problems with it. It doesn't share the problem that others have that means double clicking a header or empty space with a row selected beforehand would still cause it to run.

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
Gilgamesh
  • 498
  • 4
  • 10
5

With data binding and MVVM you would do one-click event (=selectedItem of row) like this:

    <Datagrid ItemsSource="{Binding YourObservableCollectionProperty}" 
        SelectedItem="{Binding YourSelectedItemProperty}"> 
     //more...      
    </Datagrid>

CodeBehind:

public partial class YourClass : Window
    {
        public YourClass()
        {
            InitializeComponent();
            this.DataContext = new YourClassViewModel();                      
        }
}

ViewModel:

public class YourClassViewModel : INotifyPropertyChanged
{

                public event PropertyChangedEventHandler PropertyChanged;
                public virtual void OnPropertyChanged(string propertyName)
                {
                    if (this.PropertyChanged != null)
                    {
                        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                    }
                }

                private ObservableCollection<YourModelClass> _yourObservableCollectionProperty;
                public ObservableCollection<YourModelClass> YourObservableCollectionProperty
                {
                    get { return _yourObservableCollectionProperty; }
                    set
                    {
                        _yourObservableCollectionProperty = value;
                        OnPropertyChanged("YourObservableCollectionProperty");
                    }
                }

    private YourModelClass _yourSelectedItemProperty;
    public YourModelClass YourSelectedItemProperty
    {   
           get { return _yourSelectedItemProperty; }
           set
           {
                _yourSelectedItemProperty = value;
                OnPropertyChanged("YourSelectedItemProperty");
           }    
    }

//Constructor
public YourClassViewModel()
{

       /*Take your ModelClass instance and ObservableCollection instance here 

and play around with them or move them into a method. Normally your 

observablecollection is the itemssource of your datagrid and your selecteditem 

is your modelclass.*/

    }
        }
timunix
  • 609
  • 6
  • 19
4

You could try current cell changed event handler it works only with one click and not double click if thats what your looking for, since double click can be used to for initiating editing cell or entire row or for any other process:

private void datagrid_CurrentCellChanged(object sender, EventArgs e)
    {
        int selected_index = datagrid.SelectedIndex + 1;
        // this is used for debugging and testing.
        //MessageBox.Show("The index of the row for the clicked cell is " + selected_index);

    }
0x01Brain
  • 798
  • 2
  • 12
  • 28
  • 3
    You should probably use the `SelectionChanged` event instead. The selected index seems to be lagging behind for this event. – toster-cx May 16 '16 at 13:06
2

The ItemContainerStyle do not have best solution, suggest use the RowStyle:

In your XAML:

<DataGrid.RowStyle>
    <Style TargetType="DataGridRow">        
        <EventSetter Event="MouseDoubleClick" Handler="DataGridRow_MouseDoubleClick"/>
    </Style>
</DataGrid.RowStyle>

In your Code:

private void DataGridRow_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    //your logic here
}
Darlan Dieterich
  • 2,369
  • 1
  • 27
  • 37
  • This seems better, but I'm not sure why it is the right choice - can anyone explain this in more detail? – mafu Mar 31 '20 at 10:43
  • Yes the sender is the DoubleClicked row and you can use the Item Property to have access to model binded to that row, like that. if (sender is DataGridRow dataGridRow) { dataGridRow.Item.your_model_property,,,, } – Alvaro Pereira May 06 '20 at 22:47
0

Why don't you get the SelectedRow property while the DoubleClick event happens and do something with it? If the SelectedRow is null, it means no Row is selected so just return

private void Grid_DoubleClick(object sender, RoutedEventArgs e)
{
    if(grid.SelectedRow == null)
        return; // return if there's no row selected

    // do something with the Selected row here
}
Carlo
  • 25,602
  • 32
  • 128
  • 176
  • 3
    This would not work. User could first select the row and then double click in the empty area. – Ivan Sep 18 '11 at 13:45
0

Use rowstyle and MouseDoubleClick work, like Darlan Dieterich said.

But when there are button or checkbox or other controls in cell, they will handle event but not prevent event passing to row, cause weird behavior. Use MouseDown maybe better in these case.

<DataGrid.RowStyle>
    <Style TargetType="DataGridRow">        
        <EventSetter Event="MouseDown" Handler="DataGridRow_MouseDown"/>
    </Style>
</DataGrid.RowStyle>
private void DataGridRow_MouseDown(object sender, MouseButtonEventArgs e)
{
    if(e.ClickCount != 2)
    {
        return;
    }
    // code here
            
    e.Handled = true;
}
Robin L
  • 125
  • 8