WPF: How to make DataGridCheckBoxColumn IsChecked property to bind with DataGridRow selection property to work?

Jane Jie Chen 346 Reputation points
2021-09-20T22:09:53.247+00:00

How to make DataGridCheckBoxColumn IsChecked property to bind with DataGridRow selection property to work?

We have WPF application which uses DataGrid to display collection of samples data.
We choose DataGrid control for easy to get frozen first three Columns, sorting, etc.
the first column is checkbox column. CheckBox's IsChecked property is binding with Sample's IsSelected property which is linked with DataGridRow's selection property.
the code works if assign Sample's IsSelected to true in ViewModel class. the DataGrid row is selected and checkbox is checked.
However, if click checkbox in DataGridCell in first column, the DatGrid row is selected (correct behavior).
The checkbox first is checked and then unchecked (wrong behavior).
How to fix this wrong behavior? Thx!

the code as following:

<DataGrid x:Name="gridSampleReportsList"
                                Grid.Row="2"
                                ItemsSource="{Binding SampleLists, UpdateSourceTrigger=PropertyChanged}"
                                Style="{StaticResource DataGridStyle1}"
                                AutoGenerateColumns="False"
                                SelectionMode="Extended"
                                CellStyle="{StaticResource gridCellStyle2}"
                                FrozenColumnCount="3"
                                IsReadOnly="True"
                                RowHeaderWidth="0"
                                ScrollViewer.CanContentScroll="True"
                                ScrollViewer.HorizontalScrollBarVisibility="Auto">
                                <DataGrid.Columns>
                                    <DataGridCheckBoxColumn Header="Upload" Binding="{Binding IsSelected, Mode=TwoWay}"
                                                            ElementStyle="{StaticResource CheckBoxStyle1}"
                                                            IsThreeState = "False"
                                                            Width="120">
                                    </DataGridCheckBoxColumn>
                                 <DataGrid.Columns>

DataGridRow style:

<!--<DataGrid.RowStyle>-->
                                <Style TargetType="{x:Type DataGridRow}">
                                    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                                    <!--<Setter Property="Background" Value="{Binding SampleKitLotColor}" />-->
                                    <Setter Property="MinHeight" Value="35" />
                                    <Setter Property="VerticalAlignment" Value="Center" />
                                    <Setter Property="Margin" Value="2,1" />
                                    <Setter Property="FontSize" Value="14" />
                                    <Setter Property="Padding" Value="10,5" />
                                </Style>
    <!--</DataGrid.RowStyle>-->

DataGridCell style as following:

<Style x:Key="gridCellStyle2" TargetType="{x:Type DataGridCell}">
        <Setter Property="Padding" Value="10,0,5,0" />
        <Setter Property="Foreground" Value="Black" />
        <Setter Property="Background" Value="LightGray" />
        <Setter Property="HorizontalContentAlignment" Value="Center" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type DataGridCell}">
                    <Border x:Name="borderDataGrid"
                        Margin="-1"
                            BorderBrush="LightGray"
                            BorderThickness="1.5">
                        <Grid MinHeight="35" MaxHeight="40"
                              x:Name="gridCell"
                              VerticalAlignment="Center"
                              Background="{TemplateBinding Background}">
                            <ContentPresenter VerticalAlignment="Center" />
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsSelected" Value="False" />
                                <Condition Property="IsReadOnly" Value="True" />
                            </MultiTrigger.Conditions>
                            <Setter Property="Background" Value="LightGray" />
                        </MultiTrigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsEnabled" Value="False" />
                                <Condition Property="IsReadOnly" Value="True" />
                            </MultiTrigger.Conditions>
                            <Setter Property="Background" Value="{StaticResource GroupBackgroundColor2}" />
                        </MultiTrigger>
                        <!-- this trigger does not work when clicking on grid row, it only highlights selected row and highlight three row headers-->
                        <!--<Trigger Property="IsSelected" Value="True">
                            <Setter Property="Background" TargetName="gridCell" Value="{StaticResource {x:Static SystemColors.HighlightBrushKey}}"/>
                            <Setter Property="Background" TargetName="borderDataGrid" Value="{StaticResource {x:Static SystemColors.HighlightBrushKey}}"/>
                        </Trigger>-->
                        <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridRow}}, Path=IsSelected}" Value="True">
                            <Setter Property="Background" TargetName="gridCell" Value="{StaticResource {x:Static SystemColors.HighlightBrushKey}}"/>
                            <Setter Property="Background" TargetName="borderDataGrid" Value="{StaticResource {x:Static SystemColors.HighlightBrushKey}}"/>
                            <Setter Property="Foreground" Value="White"/>
                        </DataTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>

            </Setter.Value>

        </Setter>

    </Style>

CheckBox style as following:

<Style x:Key="CheckBoxStyle1"
           TargetType="{x:Type CheckBox}">
        <Setter Property="Foreground" Value="{x:Null}" />
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="FocusVisualStyle" Value="{StaticResource EmptyCheckBoxFocusVisual}" />
        <Setter Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type CheckBox}">
                    <Grid>
                        <Border x:Name="rectangle"
                                Width="30"
                                Height="30"
                                Margin="0"
                                Background="Transparent"
                                BorderBrush="#FF000000"
                                BorderThickness="2">
                            <Path x:Name="path"
                                  Width="21"
                                  Height="21"
                                  Margin="0"
                                  HorizontalAlignment="Center"
                                  VerticalAlignment="Center"
                                  Data="M2.8245876,5.5573914 L7.6170013,11.123773 17.477438,-4.129572"
                                  Stretch="Fill"
                                  Stroke="#FF000000"
                                  StrokeDashCap="Round"
                                  StrokeEndLineCap="Round"
                                  StrokeLineJoin="Round"
                                  StrokeStartLineCap="Round"
                                  StrokeThickness="4"
                                  Visibility="Hidden" />
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="CheckBox.IsChecked" Value="True">
                            <Setter TargetName="path" Property="Visibility" Value="Visible" />
                        </Trigger>
                        <Trigger Property="HasContent" Value="true">
                            <Setter Property="FocusVisualStyle" Value="{StaticResource CheckRadioFocusVisual}" />
                            <Setter Property="Padding" Value="4,0,0,0" />
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <!--<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />-->
                            <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}" />
                            <!--<Setter TargetName="rectangle" Property="Background" Value="{StaticResource DisabledBackgroundBrush}" />-->
                            <Setter TargetName="rectangle" Property="BorderBrush" Value="#FF999999" />
                            <Setter TargetName="path" Property="Stroke" Value="#FF999999" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="BorderBrush" Value="{x:Null}" />
        <Setter Property="Background" Value="{x:Null}" />
        <Setter Property="Visibility" Value="Visible" />
    </Style>
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,671 questions
0 comments No comments
{count} votes

Accepted answer
  1. Jane Jie Chen 346 Reputation points
    2021-09-21T19:40:38.053+00:00

    The above solution works. However if it is not change the checkbox style, CheckBox looks like disabled.

    there is another solution by using checkbox's IsHitTestVisible property.
    reference the link: https://stackoverflow.com/questions/17092709/disabling-click-event-changing-ispressed-on-wpf-checkbox
    https://wpf.2000things.com/tag/ishittestvisible/

    Set the IsHitTestVisible property to false for a user interface element, 
             it will no longer respond to mouse input and will not fire mouse-related events.
             It does not disable UIElement -->
        <Style TargetType="{x:Type CheckBox}" x:Key="CheckBoxStyleClickDisable"
                                       BasedOn="{StaticResource CheckBoxStyle1}">
            <Setter Property="IsHitTestVisible" Value="False"/>
        </Style>
    
    <DataGridCheckBoxColumn Header="Upload" Binding="{Binding IsSelected, Mode=TwoWay}"
                                                                IsThreeState = "False"
                                                                ElementStyle="{StaticResource CheckBoxStyleClickDisable}"
                                                                Width="120">
    

    </DataGridCheckBoxColumn>

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Jane Jie Chen 346 Reputation points
    2021-09-21T17:02:27.177+00:00

    We found out solution: Set the CheckBox's IsEnabled to "False".
    However, when set CheckBox's IsEnabled to "False", the CheckBox control is gray out.
    so we also refine the CheckBox style and not trigger IsEnabled status so CheckBox always look enabled.

    Changed code as following:

    <DataGridCheckBoxColumn Header="Upload" Binding="{Binding IsSelected, Mode=TwoWay}"
                                                                    IsThreeState = "False"
                                                                    ElementStyle="{StaticResource **CheckBoxStyleDisable**}"
                                                                    Width="120">
                                            </DataGridCheckBoxColumn>
    
        <Style x:Key="**CheckBoxStyleDisable**"
                   TargetType="{x:Type CheckBox}">
                **<Setter Property="IsEnabled" Value="False"/>**
                <Setter Property="Foreground" Value="{x:Null}" />
                <Setter Property="BorderThickness" Value="1" />
                <Setter Property="FocusVisualStyle" Value="{StaticResource EmptyCheckBoxFocusVisual}" />
                <Setter Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}"/>
    

    The logical behind the scenes is that, since we disable the "CheckBox" IsEnabled property, click on DataGrid row (checkbox cell or other cells), it selects the row and set "IsSelected" property to true. Through binding "IsSelected" true property will set CheckBox to checked status.

    0 comments No comments