Search code examples
c#wpfmvvmdatagrid

Binding Command to element in DataGrid


I have a table with a with a column containing a bool value that I have put a checkbox in. I am trying to bind a command to the checkbox to where when I check it, it runs a command in the View Model. I'm using an MVVM structure. Here is what I have attempted so far.

<DataGrid 
                    IsReadOnly="True" 
                    Margin="0,10,0,0" 
                    ItemsSource="{Binding Diary.Diaries}" 
                    AutoGenerateColumns="False"
                    MinHeight="200" 
                    SelectionMode="Single"
                    SelectionUnit="FullRow"
                    IsSynchronizedWithCurrentItem = "True"
                    >
                    <DataGrid.Columns>
                        <DataGridTemplateColumn Header="Flagged">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <Grid >
                                        <CheckBox IsChecked="{Binding Flagged}" Command="{Binding Diary.FlagDiary}">
                                        </CheckBox>
                                    </Grid>
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn >

                        <DataGridTextColumn Header="Diary ID" Binding="{Binding DiaryID}" />       
                    </DataGrid.Columns>

                </DataGrid>

And here is the RelayCommand in the ViewModel.

FlagDiary = new RelayCommand(() =>
{
    Debug.WriteLine("Test");
});

I have been unable to get it to run the RelayCommand. Any idea what I'm doing wrong?


Solution

  • The Checkbox's DataContext would be set to one of the objects in the DataGrid's ItemSource (one of the Diary.Diaries entries). That makes the command binding invalid.

    You will need to do a relative source binding so you can get to Diary.FlagDiary. Here is one way of doing that (given the xaml you posted above).

    <CheckBox IsChecked="{Binding Flagged}"
        Command="{Binding RelativeSource={RelativeSource AncestorType=DataGrid}, Path=DataContext.Diary.FlagDiary}" />
    

    Once the command fires, you will probably want to know which Diary entry the checkbox was for... right? To do that, add a CommandParameter binding to the Checkbox. Now, the binding looks like this:

    <CheckBox IsChecked="{Binding Flagged}"
        Command="{Binding RelativeSource={RelativeSource AncestorType=DataGrid}, Path=DataContext.Diary.FlagDiary}"
        CommandParameter="{Binding}" />
    

    Your relay command code might have to change too. Probably something like this?

    FlagDiary = new RelayCommand((parameter) =>
    {
        Debug.WriteLine(parameter.ToString());
    });