Custom validation error message overlapped with other control

1.6k views Asked by At

I have create custom validator and error template. Error template is below.

<ControlTemplate x:Key="errorTmp">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="auto"></RowDefinition>
                <RowDefinition Height="auto"></RowDefinition>
            </Grid.RowDefinitions>
            <Border Grid.Row="1" BorderBrush="Red" BorderThickness="1">
                <AdornedElementPlaceholder x:Name="Adorner"/>
            </Border>                
            <TextBlock Grid.Row="0" Foreground="Red" Text="{Binding ElementName=Adorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" Margin="0,0,0,5"></TextBlock>
        </Grid>
    </ControlTemplate>

problem is error message is getting overlapped on other control.

enter image description here

2

There are 2 answers

0
mm8 On BEST ANSWER

You need to reserve space for the element in the adorner layer. You could do this by increasing the Margin property of the TextBox control itself when its Validation.HasError property returns true.

In this case you could set the top margin of the TextBox to the same height as the first row of the Grid in your Validation.ErrorTemplate:

<TextBox />

<TextBox Text="{Binding Username, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True}">
    <Validation.ErrorTemplate>
        <ControlTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="20"></RowDefinition>
                    <RowDefinition Height="auto"></RowDefinition>
                </Grid.RowDefinitions>
                <Border Grid.Row="1" BorderBrush="Red" BorderThickness="1">
                    <AdornedElementPlaceholder x:Name="Adorner"/>
                </Border>
                <TextBlock Grid.Row="0" Foreground="Red" Text="{Binding ErrorContent}"></TextBlock>
            </Grid>
        </ControlTemplate>
    </Validation.ErrorTemplate>
    <TextBox.Style>
        <Style TargetType="TextBox">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="True">
                    <!-- increase the top margin of the TextBox in order for the error content not to overlap the control above -->
                    <Setter Property="Margin" Value="0 20 0 0" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </TextBox.Style>
</TextBox>

Since the rendering of an adorner is independent from rendering of the UIElement that the adorner is bound to, there is no way for the TextBox to automatically adjusts its position when adorner is visible. That's why you have to reserve the space for the adorner element explicitly yourself.

0
Kin Chung Au On

Another possible way is to directly include another element for error displaying and set its visibility based on HasErrors property, therefore positions of other elements could be automatically adjusted.

<TextBlock x:Name="TextBlockDate" DockPanel.Dock="Left" Text="{Binding Data}"/>
<TextBlock Foreground="Red" Text="{Binding ElementName=TextBlockData, Path=(Validation.Errors)[0].ErrorContent}" Visibility="{Binding Path=HasErrors, Converter={StaticResource BooleanToVisibilityConverter}}"/>