Search code examples
c#wpfdatagrid

How to get the column value upon double-click in a WPF DataGrid?


I have the following DataGrid in a WPF Window:

<DataGrid x:Name ="ElementDataGrid" HorizontalAlignment="Left" Height="160" Margin="10,10,0,0" VerticalAlignment="Top" Width="350" SelectionChanged="ElementDataGrid_SelectionChanged">
    <DataGrid.Columns>
        <DataGridTextColumn Header ="Id" Width="*" Binding="{Binding id}">
        </DataGridTextColumn>
        <DataGridTextColumn Header ="Category" Width="*" Binding="{Binding categName}"></DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>

I want to set it in a way that if I double-click on a cell containing an id, it redirects me to a method where I could describe the functionality that needs to happen.

I tried using an EventSetter, but it does not work with DataGridTextColumn.

<EventSetter Event="MouseDoubleClick" Handler="DataGridCell_MouseDoubleClick"/>

Any code/useful documentation is highly welcome.

How do I accomplish this?


Solution

  • You can add the event setter to the cell style.

    <DataGrid.CellStyle>
       <Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource {x:Type DataGridCell}}">
          <EventSetter Event="MouseDoubleClick" Handler="DataGridCell_MouseDoubleClick"/>
       </Style>
    </DataGrid.CellStyle>
    

    From there on, you could can use the sender, which is the DataGridCell to get the value.

    private void DataGridCell_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
       var cell = (DataGridCell) sender;
       var item = (YourDataItemType) cell.DataContext;
    
       // The cell content depends on the column used.
       var textBox = (TextBox) cell.Column.GetCellContent(item);
       var value = textBox.Text;
    
       // ...do something with the value
    }
    

    Note that this is only one approach that depends on the column used, these are alternatives:

    A different way is to create your own data templates in a DataTemplateColumn and use input bindings.

    <DataGridTemplateColumn>
       <DataGridTemplateColumn.CellTemplate>
          <DataTemplate DataType="{x:Type local:YourDataItemType}">
             <TextBlock Text="{Binding id}">
                <TextBlock.InputBindings>
                   <MouseBinding MouseAction="LeftDoubleClick"
                                 Command="{Binding DataContext.MyCommand, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
                                 CommandParameter="{Binding id}"/>
                </TextBlock.InputBindings>
             </TextBlock>
          </DataTemplate>
       </DataGridTemplateColumn.CellTemplate>
       <DataGridTemplateColumn.CellEditingTemplate>
          <DataTemplate DataType="{x:Type local:YourDataItemType}">
             <TextBox Text="{Binding id}">
                <TextBox.InputBindings>
                   <MouseBinding MouseAction="LeftDoubleClick"
                                 Command="{Binding DataContext.MyCommand, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
                                 CommandParameter="{Binding categName}"/>
                </TextBox.InputBindings>
             </TextBox>
          </DataTemplate>
       </DataGridTemplateColumn.CellEditingTemplate>
    </DataGridTemplateColumn>
    

    A benefit here is that you can use commands directly and pass the value as CommandParameter.