Search code examples
wpfvalidationxamladorner

WPF Adorner Not Working if Added in Window.Resources


I am using .NET Framework 4.5 and I have following problem.

If I add Validation ErrorTemplate like this, my adorner will work and show tool tip and red circle beside my TextBox just fine:

// THIS IS WORKING FINE BUT ONLY FOR txtAge TextBox
<TextBox x:Name="txtAge" 
         Validation.Error="Validation_Error"
         Text="{Binding UpdateSourceTrigger=LostFocus, Path=Age, ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
         HorizontalAlignment="Left" MaxLength="3" Width="50">

    <Validation.ErrorTemplate>
        <ControlTemplate>
            <DockPanel LastChildFill="true">
                <Border Background="Red" DockPanel.Dock="right" Margin="5,0,0,0" Width="20" Height="20" CornerRadius="10"
                    ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
                    <TextBlock Text="!" VerticalAlignment="center" HorizontalAlignment="center" FontWeight="Bold" Foreground="white"/>
                </Border>
                <AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
                    <Border BorderBrush="red" BorderThickness="1" />
                </AdornedElementPlaceholder>
            </DockPanel>
        </ControlTemplate>
    </Validation.ErrorTemplate>
</TextBox>

So, the Validation template above is added within the <TextBox> tags for my TextBox txtAge and therefore applies only to that TextBox.

However, I would like to have a Style that applies to all TextBoxes, so I add the Adorner inside <Window.Resources> tags. But this will neither show the ToolTip nor the red circle:

// I WANT TO MAKE IT APPLY TO ALL TEXTBOXES BUT THIS IS NOT WORKING
<Window.Resources>
    <Style TargetType="{x:Type Label}">
        <Setter Property="Margin" Value="5,0,5,0" />
        <Setter Property="HorizontalAlignment" Value="Right" />
    </Style>
    <Style TargetType="{x:Type TextBox}">
        <Setter Property="VerticalAlignment" Value="Center" />
        <Setter Property="Margin" Value="0,2,40,2" />
        <Setter Property="Validation.ErrorTemplate">
            <Setter.Value>
                <ControlTemplate>
                    <DockPanel LastChildFill="true">
                        <Border Background="Red" DockPanel.Dock="right" Margin="5,0,0,0" Width="20" Height="20" CornerRadius="10"
                                ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
                            <TextBlock Text="!" VerticalAlignment="center" HorizontalAlignment="center" FontWeight="Bold" Foreground="white"/>
                        </Border>
                        <AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
                            <Border BorderBrush="red" BorderThickness="1" />
                        </AdornedElementPlaceholder>
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

Why is the 1st one working and 2nd one is not? I am new to WPF.


Solution

  • Based on @SnowballTwo answer, I figured it out.

    Move the code into Windows.Resources section and add it x:Key like below:

    <ControlTemplate x:Key="ValidationTemplate">
        <DockPanel LastChildFill="true">
            <Border Background="Red" DockPanel.Dock="right" 
                                Margin="5,0,0,0" Width="10" Height="10" CornerRadius="10"
                                ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
                <TextBlock Text="!" VerticalAlignment="center" HorizontalAlignment="center" FontWeight="Bold" Foreground="white"/>
            </Border>
            <AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
                <Border BorderBrush="red" BorderThickness="1" />
            </AdornedElementPlaceholder>
        </DockPanel>
    </ControlTemplate>
    

    Then for each TextBox, add following line to reference the ControlTemplate

    Validation.ErrorTemplate="{StaticResource ValidationTemplate}"