12

As you know you can't bind an Event directly to a command without a behaviour:

<DataGrid>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="PreviewMouseDoubleClick">
            <i:InvokeCommandAction Command="{Binding TradeEntryCommand"} />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</DataGrid>

This works perfectly fine, however now I have to refactor this from double clicking the DataGrid itself to double clicking the Cell. (I don't care which cell was clicked)

I was hoping to define this behviour now inside the Cell Style like this:

<Style x:Key="DefaultCellStyleBase" TargetType="{x:Type DataGridCell}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridCell}">
                <ControlTemplate.Triggers>
                    <EventTrigger RoutedEvent="PreviewMouseDoubleClick">
                        ?????????
                    </EventTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <!-- ... -->
</Style>

But how would I bring in the behaviour from above to fire the command?

Highly appreciated,

H.B.
  • 166,899
  • 29
  • 327
  • 400
Houman
  • 64,245
  • 87
  • 278
  • 460
  • Quite a few dupes of this already on SO related to defining behaviors in styles. In short: you can't, at least not without jumping through a LOT of complicated code-hoops. I love the EventToCommand behavior, but in cases like this I've always just had to go with a regular EventSetter with method handler on the view executing the viewmodel command. It feels dirty, it looks ugly with all of the null checking involved, but having looked at the "solutions" to this it's probably still simpler unless you find yourself running into this tons of times in a large application. – Sean Hanley Aug 16 '11 at 18:26

2 Answers2

9

Since you are retemplating the DataGridCell, you could add the triggers to the root element in the control template. Something like:

<ControlTemplate TargetType="{x:Type DataGridCell}">
    <Grid x:Name="root" Background="Transparent">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="PreviewMouseDoubleClick">
                <i:InvokeCommandAction Command="{Binding TradeEntryCommand}" />
            </i:EventTrigger>                            
        </i:Interaction.Triggers>
    </Grid>
</ControlTemplate>
AwkwardCoder
  • 24,893
  • 27
  • 82
  • 152
CodeNaked
  • 40,753
  • 6
  • 122
  • 148
  • While the code builds, i am not able to get the DataContext right, as it sits somewhere unspecified. I even tried this without success: – Houman May 11 '11 at 14:26
  • 1
    @Kave - Try: Command="{Binding DataContext.TradeEntryCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=Views:MainWindow}}" – CodeNaked May 11 '11 at 14:28
3

Thats a version I am using for a Button-command in a similar situation (Button in DataGridRow, Command on DataGrid should be invoked by the Button and I need the DataContext of the row in my command). You would have to use the command of the InvokeCommandAction of the doubleClick-trigger instead, but then it should work as well, I suppose.

Good luck!

    <DataTemplate>
            <TextBlock>                             
           <Button x:Name="cmdButton"                            
                                    Command="{Binding Path=DataContext.CommandNameInViewModel, 
                                        RelativeSource={RelativeSource AncestorType={x:Type TypeOfAncestorWithTheViewModel}}}"
                                    CommandParameter="{Binding}" >      
                                    Do something
        </Button>

    </TextBlock>  
</DataTemplate>     
Marc
  • 12,706
  • 7
  • 61
  • 97