wpfdata-bindingtextboxstaticresourcevalidationrules

Setting Validation.ErrorTemplate as Style on a WPF TextBox is causing a binding error exception


In my WPF app I have a below resource:

<ResourceDictionary>
    <Style x:Key="OnErrorTextBoxStyle" TargetType="{x:Type TextBox}"> 
        <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="True">
                <Setter Property="BorderBrush" Value="Red"/>
                <Setter Property="Validation.ErrorTemplate">
                    <Setter.Value>
                        <ControlTemplate>
                            <StackPanel>
                                <AdornedElementPlaceholder x:Name="placeholder" />
                                <TextBlock FontSize="11" FontStyle="Italic" Foreground="Red"
                               Text="{Binding ElementName=placeholder, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" />
                            </StackPanel>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Trigger>
        </Style.Triggers>
    </Style>
</ResourceDictionary>

My TextBox:

<TextBox Grid.Column="0"
         Grid.Row="1"                 
         Style="{StaticResource OnErrorTextBoxStyle}"
         Height="30"                                 
         Margin="5,8,8,15">            
    <TextBox.Text>
        <Binding Path="MyPath"
                 UpdateSourceTrigger="PropertyChanged"
                 >
            <Binding.ValidationRules>
                <Rules:PathValidationRule ValidatesOnTargetUpdated="True" />
            </Binding.ValidationRules>
        </Binding>                         
    </TextBox.Text>            
</TextBox>

In the view model my myPath property has below aspect (I only show imporant things here):

public string MyPath
{
    get => myObject.currentPath.LocalPath; // currentPath is an Uri Object

    set
    {
        if (!string.IsNullOrWhiteSpace(value))
        {
           // creates an Uri object using value and Uri.TryCreate
           if (Uri.TryCreate(value, UriKind.Absolute, out Uri newUri))
           {
               myObject.currentPath = newUri;
               OnPropertyChanged();
           }
        }
    }
}

When I try to set MyPath property from the view model I get below error:

Cannot get 'Item[]' value (type 'ValidationError') from 
'(Validation.Errors)' (type 'ReadOnlyObservableCollection`1'). 
BindingExpression:Path=AdornedElement.(0)[0].ErrorContent; 
DataItem='AdornedElementPlaceholder' (Name='placeholder'); target 
element is 'TextBlock' (Name=''); target property is 'Text' (type 
'String') 
ArgumentOutOfRangeException:'System.ArgumentOutOfRangeException: 
Specified argument was out of the range of valid values. Parameter 
name: index'

If I remove the static resource Style="{StaticResource OnErrorTextBoxStyle}" from the TextBox, then all works perfectly. So I guess I am doing something wrong in the static resource but I do not know what.

My TextBox has a validation rule which validates what user is typing in. I am not using any other validation mechanism such as INotifyDataErrorInfo and IDataErrorInfo.


Solution

  • Try this binding in the ControlTemplate:

    <TextBlock FontSize="11" FontStyle="Italic" Foreground="Red"
               Text="{Binding [0].ErrorContent}" />