From Microsoft, attempting to change the ErrorTemplate on a DataGrid just will not work. Their example is a trigger in a style where you set the background as red (or whatever) when the Validation.HasError property is true.
To customize cell validation feedback: Set the column's EditingElementStyle property to a style appropriate for the column's editing control. Because the editing controls are created at run time, you cannot use the Validation.ErrorTemplate attached property like you would with simple controls.
This approach worked for me, and it also removed the default error template (the red border around the cell). The red border is replaced with the BorderBrush in the style, and the little exclamation point can be removed by setting the RowValidationErrorTemplate property of DataGrid to {x:Null}. I have looked at the other related questions on SO and have not found this solution anywhere. Here is an example of my solution, with the style definition and a DataGridTextColumn which uses the style:
<Style
x:Key="DataGridTextBoxValidationStyle"
TargetType="{x:Type TextBox}">
<Setter Property="Padding" Value="-2" />
<Setter Property="MaxWidth" Value="250"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Width" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}}, Path=ActualWidth}"/>
<Setter Property="Height" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}}, Path=ActualHeight}"/>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="Firebrick" />
<Setter Property="Foreground" Value="White" />
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
<Setter Property="BorderBrush" Value="Firebrick"/>
</Trigger>
</Style.Triggers>
</Style>
<DataGrid RowValidationErrorTemplate="{x:Null}">
<DataGrid.Columns>
<DataGridTextColumn
EditingElementStyle="{StaticResource DataGridTextBoxValidationStyle}">
<!-- other stuff here -->
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
DispatcherTimer
) – ConcretizeDataGridCell
". in other words, the Template may get applied to the cell, BUT it's overwritten when the inner control is created. that's why you might have to capture when a Row is created, and loop through each cell to set your own value.. – Concretize