Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DataGrid bind command to row select

I want to execute a command when the user selects a row in a DataGrid.

I see it is possible to wrap cell contents in buttons (although I don't want the button style) - but I don't want to do it at the cell-level.

I also see it's possible to use behaviours to link a command to an event. But preferably I should not have to resort to behaviors for such a common task.

Is it possible to do this via plain old command databinding?

So: 1) user clicks DataGrid row 2) command on view model is fired.

like image 888
Bent Rasmussen Avatar asked Mar 10 '13 20:03

Bent Rasmussen


2 Answers

You should use "Interactivity" assembly and SelectionChanged event.

<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding People}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="ID" Binding="{Binding ID}" />
        <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
    </DataGrid.Columns>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="SelectionChanged">
            <i:InvokeCommandAction Command="{Binding MyCommand}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</DataGrid>

Where "i" is namespace:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

Also you can write binding to SelectedItem property of the DataGrid and in the set accessor you can invoke your command, but the first solution that i presented you above is better.

If you want to invoke command from main view model and pass SelectedItem from DataGrid you can use CommadParameter:

<i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
        <i:InvokeCommandAction Command="{Binding MyCommand}" 
        CommandParameter="{Binding Path=SelectedItem, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}" />
    </i:EventTrigger>
</i:Interaction.Triggers>

When items has own command you can use following code:

<i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
        <i:InvokeCommandAction Command="{Binding Path=SelectedItem.MyCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}" />
    </i:EventTrigger>
</i:Interaction.Triggers>

Or if elements has own view model that is assigned to it's DataContext, you can use following code:

 <i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
        <i:InvokeCommandAction Command="{Binding Path=SelectedItem.DataContext.MyCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}" />
    </i:EventTrigger>
</i:Interaction.Triggers>
like image 188
kmatyaszek Avatar answered Sep 28 '22 10:09

kmatyaszek


Be advised that @kmatyaszek's answer is outdated in .NET 5.0 and above, we should use Microsoft.Xaml.Behaviors instead of Microsoft.Expression.Interactions.

So the i in the namespace should be:

xmlns:i="http://schemas.microsoft.com/xaml/behaviors"

See here for details.

like image 20
Nowayout Avatar answered Sep 28 '22 12:09

Nowayout