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

时间:2016-12-22 08:54:00

标签: wpf xaml controltemplate customvalidator

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

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

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

enter image description here

2 个答案:

答案 0 :(得分:1)

您需要为装饰图层中的元素预留空间。您可以通过在其Validation.HasError属性返回true时增加TextBox控件本身的Margin属性来执行此操作。

在这种情况下,您可以将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无法自动调整其位置。这就是为什么你必须自己明确保留adorner元素的空间。

答案 1 :(得分:0)

另一种可能的方式是直接包含另一个元素进行错误显示,并根据 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}}"/>