Search code examples
c#wpfdatagridstyles

WPF DataGrid Row Header


I have a design from our project UI Designer. The design is for datagrids within our App. Within the design he has defined that the datagrid should always have a left margin of 32px BUT, the horizontal grid lines should continue to the edge of the container.

In order to do this I thought I would add in the RowHeader which gives me the desired output. The issue I am facing is on MouseOver of the DataGridRow I am changing the Row Background, but the RowHeader is not recoloured. I added a MouseOver trigger to the RowHeader but this only works when MouseOver is on the RowHeader.

Can anyone suggest how to set the RowHeader Background on Row MouseOver.

Here is how my DataGrid looks on screen, I have hovered a row to highlight the issue I face:

Screenshot of Current DataGrid output

My current Style for the DataGrid:

  <Style TargetType="{x:Type DataGrid}">

    <Setter Property="AutoGenerateColumns" Value="False" />
    <Setter Property="Background" Value="{DynamicResource BackgroundBrush}" />
    <Setter Property="BorderBrush" Value="{DynamicResource DataGridColumnHeader.BorderBrush}" />
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="CanUserReorderColumns" Value="False" />
    <Setter Property="CanUserResizeColumns" Value="False" />
    <Setter Property="CanUserResizeRows" Value="False" />
    <Setter Property="ColumnHeaderHeight" Value="44" />
    <Setter Property="Cursor" Value="Hand" />
    <Setter Property="FontFamily" Value="{DynamicResource Inter}" />
    <Setter Property="FontSize" Value="{DynamicResource Font_Medium}" />
    <Setter Property="FontWeight" Value="{DynamicResource 500}" />
    <Setter Property="FocusVisualStyle" Value="{x:Null}" />
    <Setter Property="Foreground" Value="{DynamicResource ForegroundBrush}"/>
    <Setter Property="GridLinesVisibility" Value="Horizontal" />
    <Setter Property="HeadersVisibility" Value="All" />
    <Setter Property="HorizontalGridLinesBrush" Value="{DynamicResource DataGrid.GridLines.BorderBrush}" />
    <Setter Property="IsReadOnly" Value="True" />
    <Setter Property="RowDetailsVisibilityMode" Value="VisibleWhenSelected"/>
    <Setter Property="RowHeaderWidth" Value="32" />
    <Setter Property="RowHeight" Value="40" />
    <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
    <Setter Property="ScrollViewer.PanningMode" Value="Both"/>
    <Setter Property="SelectionMode" Value="Single" />
    <Setter Property="SelectionUnit" Value="FullRow" />
    <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
    <Setter Property="VerticalContentAlignment" Value="Center" />

    <Setter Property="Template">

      <Setter.Value>

        <ControlTemplate TargetType="{x:Type DataGrid}">

          <Border Background="{TemplateBinding Background}" 
                  BorderBrush="{TemplateBinding BorderBrush}"
                  BorderThickness="{TemplateBinding BorderThickness}"
                  Padding="{TemplateBinding Padding}" 
                  SnapsToDevicePixels="True">
            
            <ScrollViewer x:Name="dataGridScrollViewer" 
                          Focusable="false">

              <ScrollViewer.Template>

                <ControlTemplate TargetType="{x:Type ScrollViewer}">

                  <Grid>

                    <Grid.ColumnDefinitions>
                      <ColumnDefinition Width="Auto"/>
                      <ColumnDefinition Width="*"/>
                      <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>

                    <Grid.RowDefinitions>
                      <RowDefinition Height="Auto"/>
                      <RowDefinition Height="*"/>
                      <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>

                    <Border Background="{Binding Background, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
                            BorderBrush="{Binding BorderBrush, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
                            BorderThickness="0,0,0,1"
                            Grid.Column="0"
                            Grid.Row="0"
                            Opacity="1"
                            Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />

                    <DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter" 
                                                    Grid.Column="1" 
                                                    Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column},
                                                                                            Converter={x:Static DataGrid.HeadersVisibilityConverter},
                                                                                            RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>

                    <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" 
                                            CanContentScroll="{TemplateBinding CanContentScroll}" 
                                            Grid.ColumnSpan="2" Grid.Row="1"/>

                    <ScrollBar x:Name="PART_VerticalScrollBar" 
                               Grid.Column="2" 
                               Grid.Row="1" 
                               Maximum="{TemplateBinding ScrollableHeight}" 
                               Orientation="Vertical" 
                               Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}}" 
                               ViewportSize="{TemplateBinding ViewportHeight}" 
                               Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
                    
                    <Grid Grid.Column="1" 
                          Grid.Row="2">

                      <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="{Binding NonFrozenColumnsViewportHorizontalOffset, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
                        <ColumnDefinition Width="*"/>
                      </Grid.ColumnDefinitions>

                      <ScrollBar x:Name="PART_HorizontalScrollBar" 
                                 Grid.Column="1" 
                                 Maximum="{TemplateBinding ScrollableWidth}" 
                                 Orientation="Horizontal" 
                                 Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}}" 
                                 ViewportSize="{TemplateBinding ViewportWidth}" 
                                 Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>

                    </Grid>

                  </Grid>

                </ControlTemplate>

              </ScrollViewer.Template>

              <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>

            </ScrollViewer>

          </Border>

        </ControlTemplate>

      </Setter.Value>

    </Setter>

    <Setter Property="CellStyle">

      <Setter.Value>

        <Style TargetType="{x:Type DataGridCell}">

          <Setter Property="Background" Value="Transparent" />
          <Setter Property="BorderBrush" Value="{Binding BorderBrush, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
          <Setter Property="Cursor" Value="Hand" />
          <Setter Property="FontFamily" Value="{Binding FontFamily, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
          <Setter Property="FontSize" Value="{Binding FontSize, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
          <Setter Property="FontWeight" Value="{Binding FontWeight, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
          <Setter Property="Foreground" Value="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />

          <Setter Property="Template">

            <Setter.Value>

              <ControlTemplate TargetType="{x:Type DataGridCell}">

                <Grid Background="{TemplateBinding Background}">
                  <ContentPresenter HorizontalAlignment="Left"
                                    VerticalAlignment="Center" />
                </Grid>

                <ControlTemplate.Triggers>

                  <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Foreground" Value="{DynamicResource DataGrid.Foreground.Focus}" />
                  </Trigger>

                </ControlTemplate.Triggers>

              </ControlTemplate>

            </Setter.Value>

          </Setter>

        </Style>

      </Setter.Value>
      
    </Setter>

    <Setter Property="RowStyle">
      
      <Setter.Value>

        <Style TargetType="{x:Type DataGridRow}">

          <Setter Property="Background" Value="{Binding Background, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
          <Setter Property="Foreground" Value="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />

          <Style.Triggers>

            <Trigger Property="IsMouseOver" Value="True">
              <Setter Property="Background" Value="{DynamicResource DataGrid.Background.Hover}" />
            </Trigger>

            <MultiTrigger>

              <MultiTrigger.Conditions>
                <Condition Property="IsSelected" Value="True"/>
                <Condition Property="Selector.IsSelectionActive" Value="False" />
              </MultiTrigger.Conditions>

              <Setter Property="Background" Value="{DynamicResource DataGrid.Background.Focus.Inactive}"/>
              <Setter Property="Foreground" Value="{DynamicResource DataGrid.Foreground.Focus}"/>

            </MultiTrigger>

            <MultiTrigger>

              <MultiTrigger.Conditions>
                <Condition Property="IsSelected" Value="True"/>
                <Condition Property="Selector.IsSelectionActive" Value="True" />
              </MultiTrigger.Conditions>

              <Setter Property="Background" Value="{DynamicResource DataGrid.Background.Focus}"/>
              <Setter Property="Foreground" Value="{DynamicResource DataGrid.Foreground.Focus}"/>

            </MultiTrigger>

          </Style.Triggers>

        </Style>

      </Setter.Value>
      
    </Setter>

    <Style.Triggers>

      <MultiTrigger>
        <MultiTrigger.Conditions>
          <Condition Property="IsGrouping" Value="true"/>
          <Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="false"/>
        </MultiTrigger.Conditions>
        <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
      </MultiTrigger>

    </Style.Triggers>

  </Style>

  <Style TargetType="{x:Type DataGridColumnHeader}">

    <Setter Property="Background" Value="{Binding Background, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
    <Setter Property="BorderBrush" Value="{Binding BorderBrush, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
    <Setter Property="BorderThickness" Value="0,0,0,1" />
    <Setter Property="Cursor" Value="{Binding Cursor, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
    <Setter Property="FocusVisualStyle" Value="{x:Null}" />
    <Setter Property="FontFamily" Value="{Binding FontFamily, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
    <Setter Property="FontSize" Value="{DynamicResource Font_Regular}" />
    <Setter Property="FontWeight" Value="{Binding FontWeight, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
    <Setter Property="Foreground" Value="{StaticResource DataGridColumnHeader.Foreground}" />
    <Setter Property="Height" Value="{Binding ColumnHeaderHeight, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />

    <Setter Property="Template">

      <Setter.Value>

        <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">

          <ControlTemplate.Resources>

            <Style x:Key="ColumnHeaderGripperStyle" TargetType="{x:Type Thumb}">

              <Setter Property="Background" Value="Transparent"/>
              <Setter Property="Cursor" Value="SizeWE"/>
              <Setter Property="Width" Value="8"/>

              <Setter Property="Template">

                <Setter.Value>

                  <ControlTemplate TargetType="{x:Type Thumb}">

                    <Border Background="{TemplateBinding Background}"
                            Padding="{TemplateBinding Padding}"/>

                  </ControlTemplate>

                </Setter.Value>

              </Setter>

            </Style>

          </ControlTemplate.Resources>

          <Grid>

            <Border x:Name="border"
                    Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}">

              <Grid x:Name="content">

                <Grid.ColumnDefinitions>
                  <ColumnDefinition Width="Auto" />
                  <ColumnDefinition Width="30" />
                </Grid.ColumnDefinitions>

                <ContentPresenter Grid.Column="0"
                                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                  RecognizesAccessKey="True" 
                                  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                
                <Path x:Name="SortingArrow"
                      Cursor="Hand"
                      Data="M12.4336 6.61328C12.5703 6.72266 12.5703 6.94141 12.4336 7.07812L6.71875 12.793C6.58203 
                            12.9297 6.39062 12.9297 6.25391 12.793L0.539062 7.07812C0.402344 6.94141 0.402344 
                            6.72266 0.539062 6.61328L1.05859 6.06641C1.19531 5.92969 1.41406 5.92969 1.52344 
                            6.06641L5.78906 10.3047V0.953125C5.78906 0.789062 5.92578 0.625 6.11719 0.625H6.88281C7.04688 
                            0.625 7.21094 0.789062 7.21094 0.953125V10.3047L11.4492 6.06641C11.5586 5.92969 11.7773 5.92969 
                            11.9141 6.06641L12.4336 6.61328Z"
                      Fill="{StaticResource DataGridColumnHeader.Foreground}"
                      Grid.Column="1" 
                      Height="13" 
                      HorizontalAlignment="Center" 
                      RenderTransformOrigin="0.5,0.5"
                      VerticalAlignment="Center" 
                      Visibility="Collapsed"
                      Width="13" />

              </Grid>

            </Border>

            <Thumb x:Name="PART_LeftHeaderGripper" 
                   HorizontalAlignment="Left" 
                   Style="{StaticResource ColumnHeaderGripperStyle}"/>

            <Thumb x:Name="PART_RightHeaderGripper" 
                   HorizontalAlignment="Right" 
                   Style="{StaticResource ColumnHeaderGripperStyle}"/>

          </Grid>

          <ControlTemplate.Triggers>

            <Trigger Property="SortDirection" Value="Ascending">

              <Setter TargetName="SortingArrow" Property="Visibility" Value="Visible" />
              <Setter TargetName="SortingArrow" Property="RenderTransform">
                
                <Setter.Value>
                  <RotateTransform Angle="180" />
                </Setter.Value>
              </Setter>

            </Trigger>

            <Trigger Property="SortDirection" Value="Descending">
              <Setter TargetName="SortingArrow" Property="Visibility" Value="Visible" />
            </Trigger>

          </ControlTemplate.Triggers>

        </ControlTemplate>

      </Setter.Value>

    </Setter>

  </Style>

  <Style TargetType="{x:Type DataGridRowHeader}">

    <Setter Property="Background" Value="{Binding Background, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
    <Setter Property="BorderBrush" Value="{DynamicResource DataGrid.GridLines.BorderBrush}" />
    <Setter Property="BorderThickness" Value="0,0,0,1" />
    <Setter Property="Cursor" Value="{Binding Cursor, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
    <Setter Property="FocusVisualStyle" Value="{Binding FocusVisualStyle, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
    <Setter Property="Width" Value="{Binding RowHeaderWidth, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />

    <Style.Triggers>

      <Trigger Property="IsMouseOver" Value="True">
        <Setter Property="Background" Value="{DynamicResource DataGrid.Background.Hover}" />
      </Trigger>

      <MultiTrigger>

        <MultiTrigger.Conditions>
          <Condition Property="IsRowSelected" Value="true"/>
          <Condition Property="Selector.IsSelectionActive" Value="false"/>
        </MultiTrigger.Conditions>

        <Setter Property="Background" Value="{DynamicResource DataGrid.Background.Focus.Inactive}"/>
        <Setter Property="Foreground" Value="{DynamicResource DataGrid.Foreground.Focus}"/>

      </MultiTrigger>

      <MultiTrigger>

        <MultiTrigger.Conditions>
          <Condition Property="IsRowSelected" Value="True"/>
          <Condition Property="Selector.IsSelectionActive" Value="True" />
        </MultiTrigger.Conditions>

        <Setter Property="Background" Value="{DynamicResource DataGrid.Background.Focus}"/>
        <Setter Property="Foreground" Value="{DynamicResource DataGrid.Foreground.Focus}"/>

      </MultiTrigger>

    </Style.Triggers>

  </Style>

Solution

  • You just need to add a margin to the ContentPresenter in the CellStyle:

    <Setter Property="CellStyle">
      <Setter.Value>
        <Style TargetType="{x:Type DataGridCell}">
          <Setter Property="Background" Value="Transparent" />
          <Setter Property="BorderBrush" Value="{Binding BorderBrush, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
          <Setter Property="Cursor" Value="Hand" />
          <Setter Property="FontFamily" Value="{Binding FontFamily, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
          <Setter Property="FontSize" Value="{Binding FontSize, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
          <Setter Property="FontWeight" Value="{Binding FontWeight, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
          <Setter Property="Foreground" Value="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="{x:Type DataGridCell}">
                <Grid Background="{TemplateBinding Background}">
                  <ContentPresenter Margin="32 0 0 0"
                                    HorizontalAlignment="Left"
                                    VerticalAlignment="Center" />
                </Grid>
                <ControlTemplate.Triggers>
                  <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Foreground" Value="{DynamicResource DataGrid.Foreground.Focus}" />
                  </Trigger>
                </ControlTemplate.Triggers>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Style>
      </Setter.Value>
    </Setter>