自定义验证错误消息与其他控件重叠
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}}"/>
我已经创建了自定义验证器和错误模板。错误模板如下。
<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}}"/>