Search code examples
wpfxamlwpfdatagrid

Style a WPF DataGrid row header when the selected cell resides in that row?


I have a WPF DataGrid that is configured to only allow a single cell selection, i.e.:-

SelectionMode="Single"
SelectionUnit="Cell"

What I'm trying to do is change the background of the row header of whichever row contains the currently selected cell. I've come up with the following so far, but it isn't working.

Here is the XAML style, which binds the background property to a multi-value converter. The converter is bound to the header's DataGridRow and the SelectedCells property of the DataGrid:-

<Style TargetType="{x:Type DataGridRowHeader}">
    <Setter Property="Background">
        <Setter.Value>
            <MultiBinding Converter="{StaticResource dataGridHeaderBackgroundConverter}" Mode="OneWay">
                <Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridRow}}" />
                <Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}" 
                         Path="SelectedCells"
                         Mode="OneWay"/>
            </MultiBinding>
        </Setter.Value>
    </Setter>
</Style>

The multi-converter's Convert method looks like this (I've removed null checking code to keep it concise):-

var row = values[0] as DataGridRow;
var selectedCells = values[1] as IList<DataGridCellInfo>;
var selectedCell = selectedCells[0];

return selectedCell.Item == row.Item ? Colors.Red : Colors.LightGray;

The method only seems to get called when the DataGrid is initially rendered (when there are no selections). It doesn't get called after a cell has been selected, so what am I missing?


Solution

  • You can update your style as follows and write the EqualityConverter which would be a MultiValueConverter to be used to bind the DataGrid's CurrentCell and RowHeader context in the DataTrigger. So this trigger will be fired everytime you select the cell on your DataGrid.

      <Style TargetType="{x:Type DataGridRowHeader}">
                <Style.Triggers>
                    <DataTrigger  Value="true">
                        <DataTrigger.Binding>
                            <MultiBinding Converter="{StaticResource EqualityConverter}">
                                <Binding/>
                                <Binding Path="CurrentCell" RelativeSource="{RelativeSource AncestorType={x:Type DataGrid}}"/>
                            </MultiBinding>
                        </DataTrigger.Binding>
                        <Setter Property="Background" Value="Black"/>
                    </DataTrigger>
                </Style.Triggers>
    
            </Style>
    

    and in converter's Convert method:

                if(values[0] == ((DataGridCellInfo)values[1]).Item)
                {
                    return true;
                }
                return false;
    

    Tested it.. worked well