4
votes

I have a DataGrid using an inline style that adds a tooltip for reporting error messages - I am binding it to a collection implementing IDataErrorInfo.

In particular, I have a column bound to an integer with IDataErrorInfo logic to not permit the value outside a certain range - when I violate this rule, the default error behavior applies (eg the Textbox is highlighted red) instead of activating my error style, however if I trigger an error by entering text into the textbox and causing an InvalidInputString format, it will trigger my error style, like the way I want it to.

Here is my XAML:

<DataGrid ItemsSource="{x:Static local:WeatherForecast.TomorrowsForecast}" AutoGenerateColumns="False">
        <DataGrid.Resources>
            <Style x:Key="errorStyle" TargetType="{x:Type TextBox}">
                <Setter Property="Padding" Value="-2"/>
                <Style.Triggers>
                    <Trigger Property="Validation.HasError" Value="True">
                        <Setter Property="Background" Value="PeachPuff"/>
                        <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </DataGrid.Resources>

        <DataGrid.Columns>
            <DataGridTextColumn Header="City" Binding="{Binding Path=Planet}"/>
            <DataGridTextColumn Header="Low Temperature" Binding="{Binding Path=LowestTemp, ValidatesOnExceptions=True, ValidatesOnDataErrors=True}" EditingElementStyle="{StaticResource errorStyle}" />
            <DataGridTextColumn Header="High Temperature" Binding="{Binding Path=HighestTemp, ValidatesOnExceptions=True, ValidatesOnDataErrors=True}" EditingElementStyle="{StaticResource errorStyle}" />
        </DataGrid.Columns>
    </DataGrid>

My simple IDateErrorInfo logic is:

    public string this[string columnName]
    {
        get 
        {
            // Temperature range checks.
            if ((columnName == "LowestTemp") || (columnName == "HighestTemp"))
            {
                if ((this.LowestTemp < -273) || (this.HighestTemp < -273))
                {
                    return "Temperature can not be below the absolute cold (-273°C).";
                }
            }

            // All validations passed successfully.
            return null;

        }
    }

Why is the default error validation behavior of a red border firing, but not my style?

UPDATE:

This seems to work fine when done OUTSIDE the DataGrid eg if I have two stray textboxes binding to one instance of my object

<TextBlock>Lowest Temp</TextBlock>
    <TextBox Width="100" DataContext="{StaticResource instance}" Text="{Binding Path=LowestTemp, NotifyOnValidationError=True, ValidatesOnExceptions=True, ValidatesOnDataErrors=True}" Style="{StaticResource errorStyle}" />
    <TextBlock>Highest Temp</TextBlock>
    <TextBox Width="100" DataContext="{StaticResource instance}" Text="{Binding Path=HighestTemp, NotifyOnValidationError=True, ValidatesOnExceptions=True, ValidatesOnDataErrors=True}" Style="{StaticResource errorStyle}" />

It works fine! Any idea what it is about the DataGrid's internals that may be preventing this behavior from working?

1

1 Answers

0
votes

You are missing NotifyOnValidationError=True on your DataGridTextColumn