Search code examples
wpfmaterial-design-in-xaml

DataGridCell IsReadOnly ControlTemplate trigger to change background color -


The goal is to assign proper color to the wrapping border (that makes the ControlTemplate targeting DataGridCell) when the columns has IsReadOnly set to false.

<Style BasedOn="{StaticResource MaterialDesignDataGridCell}" TargetType="{x:Type DataGridCell}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridCell}">
                <Border
            Margin="8"
            Background="{TemplateBinding Background}"
            CornerRadius="4">
                    <Grid>
                        <ContentPresenter VerticalAlignment="Center" />
                    </Grid>
                </Border>

                <ControlTemplate.Triggers>
                    <Trigger Property="IsReadOnly" Value="False">
                        <Setter Property="Background" Value="{StaticResource SecondaryHueMidBrush}" />
                        <Setter Property="Foreground" Value="{StaticResource MaterialDesignDarkForeground}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

The color is assigned correctly enter image description here

However when some row is selected and then cursor leaves the mentioned row, the assigned coloring disappears and I am left with the default one. It happens only when the row is still selected.

enter image description here

The considered columns which are the only ones which are not ReadOnly are defined in the following way

<DataGridTextColumn
    Binding="{Binding PreviousMonthResult, UpdateSourceTrigger=PropertyChanged}"
    EditingElementStyle="{StaticResource textCenterEditing}"
    ElementStyle="{StaticResource textCenter}">
    <DataGridTextColumn.HeaderTemplate>
        <DataTemplate>
            <Border
                Padding="8"
                Background="{StaticResource SecondaryHueMidBrush}"
                CornerRadius="8">
                <TextBlock Foreground="{StaticResource MaterialDesignDarkForeground}" Text="{Binding DataContext.DateHeaders[PreviousMonth], RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
            </Border>
        </DataTemplate>
    </DataGridTextColumn.HeaderTemplate>
</DataGridTextColumn>
<DataGridTextColumn
    Binding="{Binding CurrentMonthResult, UpdateSourceTrigger=PropertyChanged}"
    EditingElementStyle="{StaticResource textCenterEditing}"
    ElementStyle="{StaticResource textCenter}">
    <DataGridTextColumn.HeaderTemplate>
        <DataTemplate>
            <Border
                Padding="8"
                Background="{StaticResource SecondaryHueMidBrush}"
                CornerRadius="8">
                <TextBlock Foreground="{StaticResource MaterialDesignDarkForeground}" Text="{Binding DataContext.DateHeaders[CurrentMonth], RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
            </Border>
        </DataTemplate>
    </DataGridTextColumn.HeaderTemplate>
</DataGridTextColumn>

Where textCenterEditing and textCenter

<Style BasedOn="{StaticResource MaterialDesignDataGridColumnHeader}" TargetType="DataGridColumnHeader">
    <Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>

<Style x:Key="textCenter" TargetType="{x:Type TextBlock}">
    <Setter Property="TextAlignment" Value="Center" />
</Style>

<Style
    x:Key="textCenterEditing"
    BasedOn="{StaticResource MaterialDesignTextBox}"
    TargetType="{x:Type TextBox}">
    <Setter Property="TextAlignment" Value="Center" />
</Style>

However I guess these "small" styles should not interfere with achieving the desired result


Solution

  • You're using some material design styling there which might be a complication, not sure.

    The problem is due to the selected brush, applied at row level.

    If you're not bothered about highlighting selected row background the you can set it transparent.

    Roughly:

    <DataGrid.Resources>
        <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="Transparent"/>
     </DataGrid.Resources>
    

    You might want to use the foreground brush to denote selection.

    There might possibly be a more elegant material design orientated solution.