自定义验证错误消息与其他控件重叠

Custom validation error message overlapped with other control

我已经创建了自定义验证器和错误模板。错误模板如下。

<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>

问题是错误消息在其他控件上重叠。

您需要为装饰层中的元素保留 space。您可以通过在 Validation.HasError 属性 returns 为真时增加 TextBox 控件本身的边距 属性 来实现。

在这种情况下,您可以将 TextBox 的上边距设置为与 Validation.ErrorTemplate 中 Grid 的第一行相同的高度:

<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>

由于装饰器的呈现独立于装饰器绑定到的 UIElement 的呈现,因此当装饰器可见时,TextBox 无法自动调整其位置。这就是为什么您必须自己明确地为装饰元素保留 space。

另一种可能的方法是直接包含另一个元素用于错误显示,并根据HasErrors设置其可见性 属性,因此其他元素的位置可以自动调整。

<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}}"/>