WPF 验证 - 显示 StackPanel 中元素的错误
WPF validation - displaying errors for elements in StackPanel
我在垂直 StackPanel 中如何为 TextBox 元素显示验证错误时遇到问题。我正在尝试在文本框下方显示错误消息。
我有这个错误模板:
<Style TargetType="{x:Type TextBox}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel>
<AdornedElementPlaceholder />
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding (ValidationError.ErrorContent)}" Foreground="Red" Margin="5"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
如果我在 TextBox 下方有足够的白色 space,则错误显示正常,但在 StackPanel 中(例如),它不会为错误消息添加额外的边距或填充,因为装饰层。
预计会是这样,根据this source:
Note that the Validation.ErrorTemplate will be displayed on the adorner layer. Elements in the adorner layer are rendered on top of the rest of the visual elements and they will not be considered when the layout system is measuring and arranging the controls on the adorned element layer.
如何显示验证错误消息,以便它们不会显示在 StackPanel 中的其他元素之上?
好的,我找到了转换器的解决方案。我最终得到了类似这样的风格:
<Style TargetType="{x:Type TextBox}">
<Setter Property="Margin" Value="10" />
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel>
<AdornedElementPlaceholder />
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding (ValidationError.ErrorContent)}" Foreground="Red" Margin="0,5"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Trigger.Setters>
<Setter Property="Margin" Value="{Binding (Validation.Errors).Count, RelativeSource={RelativeSource Self}, Converter={StaticResource ErrorsToMarginConverter}}"/>
</Trigger.Setters>
</Trigger>
</Style.Triggers>
</Style>
和转换器:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is int)
{
var errors = (int)value;
return new Thickness(10, 10, 10, (errors * 20));
}
return value;
}
您还可以考虑将您的错误模板包含在文本框的模板中。
诸如此类(当然可以改进):
<Style x:Key="eTextBox" TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<StackPanel>
<Border BorderBrush="Gray" BorderThickness="1" CornerRadius="1" Padding="2">
<ScrollViewer Name="PART_ContentHost" Focusable="False"
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
Background="#00FFFFFF" />
</Border>
<ItemsControl ItemsSource="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=(Validation.Errors)}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding (ValidationError.ErrorContent)}" Foreground="Red" Margin="5"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
通过这种方式,ItemsControl 被考虑用于布局计算。
我在垂直 StackPanel 中如何为 TextBox 元素显示验证错误时遇到问题。我正在尝试在文本框下方显示错误消息。
我有这个错误模板:
<Style TargetType="{x:Type TextBox}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel>
<AdornedElementPlaceholder />
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding (ValidationError.ErrorContent)}" Foreground="Red" Margin="5"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
如果我在 TextBox 下方有足够的白色 space,则错误显示正常,但在 StackPanel 中(例如),它不会为错误消息添加额外的边距或填充,因为装饰层。
预计会是这样,根据this source:
Note that the Validation.ErrorTemplate will be displayed on the adorner layer. Elements in the adorner layer are rendered on top of the rest of the visual elements and they will not be considered when the layout system is measuring and arranging the controls on the adorned element layer.
如何显示验证错误消息,以便它们不会显示在 StackPanel 中的其他元素之上?
好的,我找到了转换器的解决方案。我最终得到了类似这样的风格:
<Style TargetType="{x:Type TextBox}">
<Setter Property="Margin" Value="10" />
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel>
<AdornedElementPlaceholder />
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding (ValidationError.ErrorContent)}" Foreground="Red" Margin="0,5"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Trigger.Setters>
<Setter Property="Margin" Value="{Binding (Validation.Errors).Count, RelativeSource={RelativeSource Self}, Converter={StaticResource ErrorsToMarginConverter}}"/>
</Trigger.Setters>
</Trigger>
</Style.Triggers>
</Style>
和转换器:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is int)
{
var errors = (int)value;
return new Thickness(10, 10, 10, (errors * 20));
}
return value;
}
您还可以考虑将您的错误模板包含在文本框的模板中。 诸如此类(当然可以改进):
<Style x:Key="eTextBox" TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<StackPanel>
<Border BorderBrush="Gray" BorderThickness="1" CornerRadius="1" Padding="2">
<ScrollViewer Name="PART_ContentHost" Focusable="False"
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
Background="#00FFFFFF" />
</Border>
<ItemsControl ItemsSource="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=(Validation.Errors)}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding (ValidationError.ErrorContent)}" Foreground="Red" Margin="5"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
通过这种方式,ItemsControl 被考虑用于布局计算。