我有一个MainWindow和一个UserControl。MainWindow显示UserControl。UserControl本身遵循MVVM模式,并在ViewModel中实现IDataErrorInfo接口。这很好,但是Validation.ErrorTemplate没有显示。
我的UserControl.xaml
<TextBox x:Name="txtName"
Text="{Binding Path=Name, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True}"
Grid.Row="0" Grid.Column="2"
VerticalAlignment="Bottom" MinWidth="100" FontSize="12">
<TextBox.Resources>
<Style TargetType="TextBox">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel Orientation="Horizontal">
<AdornedElementPlaceholder>
<Border BorderBrush="Red" BorderThickness="1"/>
</AdornedElementPlaceholder>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Resources>
</TextBox>ToolTip显示正确,但TextBox的红色边框仅当我使用Snoop并在VisualTree中选择TextBox时显示。
所以我漏掉了什么?有扳机吗?
我在两本书里查到了这个例子,这些例子都很有用。根据UserControl的说法,这是一个错误吗?我必须以某种方式手动更新它吗?
现在,编辑,当我只这样使用它时,我完全糊涂了:
<TextBox x:Name="txtName"
Text="{Binding Path=Name, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True}"
Grid.Row="0" Grid.Column="2"
VerticalAlignment="Bottom" MinWidth="100" FontSize="12">
<TextBox.Resources>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
<Setter Property="BorderBrush" Value="Red"/>
<Setter Property="BorderThickness" Value="3"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Resources>
</TextBox>BorderBrush和BorderThickness总是“红色”/“3”!为什么或者怎么触发才能使它倒退?根据这一点:使用Validation.HasError触发器属性WPF时只显示假样式应该在清除Validation.HasError时出现默认值。
发布于 2014-07-31 15:10:05
因此,我发现了我的错误(或者至少是为什么Validation.HasError从未重置的部分),我错误地使用了IDataErrorInfo接口。如果验证通过,我没有返回null或String.Empty。:(
//Not used in WPF so return value is null
string IDataErrorInfo.Error { get { return null; } }
string IDataErrorInfo.this[string propertyName]
{
get
{
//the wrong way
string error = "false way";
//the right way
string error = null;
//or
string error = String.Empty;
switch (propertyName)
{
case ("name"):
if (string.IsNullOrEmpty(name) || name.Trim() == String.Empty)
{
error = "Enter name";
}
break;
case ("age"):
if (string.IsNullOrEmpty(age) || age.Trim() == String.Empty)
{
error = "Enter age";
}
break;
default:
Debug.Fail("Validation: Unexpected property: " + propertyName);
break;
}
return error;
}
}编辑有时我会得到这个错误,没有修剪.
System.Windows.Data错误: 17 :无法从'(Validation.Errors)‘获取'Item[]’值(键入'ValidationError') (键入‘Validation.Errors’1‘)。ArgumentOutOfRangeException:'System.ArgumentOutOfRangeException: BindingExpression:Path=(0).ErrorContent;DataItem='TextBox‘(Name='txtName');目标元素是'TextBox’(Name='txtName');目标属性是'ToolTip‘(类型'Object')
发布于 2015-04-06 19:54:23
我意识到这是一个旧的帖子,你可能已经转移到更大更好的事情上去了,但我想我会给那些发现这个问题的人一个答案,因为他们和我一样,也在努力解决类似的问题。
我也有类似的问题。对我来说,答案是
Path=(Validation.Errors)[0].ErrorContent使用
Path=(Validation.Errors).CurrentItem.ErrorContent这个处理掉了
System.Windows.Data Error: 17 : Cannot get 'Item[]' value (type 'ValidationError') from '(Validation.Errors)' (type 'ReadOnlyObservableCollection`1').您在编辑时向您的答案报告错误。另外,请参阅这个博客 (它给了我这个想法)以获得更多细节。
发布于 2014-07-30 14:19:31
我认为你需要把Border移动到AdornedElementPlaceholder周围。下面是我使用的ValidationTemplate,它有一个剪切角,当您悬停在它上面时,它会显示错误消息。
<ControlTemplate x:Key="ErrorTemplate">
<StackPanel>
<!--TextBox Error template-->
<Canvas Panel.ZIndex="1099">
<DockPanel>
<Border BorderThickness="1" BorderBrush="#FFdc000c" CornerRadius="0.7"
VerticalAlignment="Top" DockPanel.Dock="Bottom" HorizontalAlignment="Left">
<Grid>
<Polygon x:Name="toolTipCorner"
Grid.ZIndex="2"
Margin="-1"
Points="11,11 11,0 0,0"
Fill="#FFdc000c"
HorizontalAlignment="Right"
VerticalAlignment="Top"
IsHitTestVisible="True"/>
<Polyline Grid.ZIndex="3"
Points="12,12 0,0" Margin="-1" HorizontalAlignment="Right"
StrokeThickness="1.5"
StrokeEndLineCap="Round"
StrokeStartLineCap="Round"
Stroke="White"
VerticalAlignment="Top"
IsHitTestVisible="True"/>
<AdornedElementPlaceholder x:Name="ErrorAdorner" />
</Grid>
</Border>
</DockPanel>
<Popup x:Name="ErrorPopup" Opacity="0" IsOpen="False" AllowsTransparency="True" Placement="Bottom" PlacementTarget="{Binding ElementName=ErrorAdorner}" StaysOpen="True">
<Border Canvas.Bottom="4"
x:Name="errorBorder"
Canvas.Left="{Binding Path=AdornedElement.ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Adorner}}"
CornerRadius="5"
Background="#FFdc000c">
<Border.Effect>
<DropShadowEffect ShadowDepth="2.25"
Color="Black"
Opacity="0.4"
Direction="315"
BlurRadius="4"/>
</Border.Effect>
<TextBlock TextWrapping="Wrap" Margin="4"
MaxWidth="250" Foreground="White"
FontSize="12"
Text="{Binding Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Adorner}}" />
</Border>
</Popup>
</Canvas>
</StackPanel>
<ControlTemplate.Triggers>
<DataTrigger Value="True" Binding="{Binding ElementName=toolTipCorner, Path=IsMouseOver}">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="fadeInStoryboard">
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="ErrorPopup"
Storyboard.TargetProperty="IsOpen">
<DiscreteBooleanKeyFrame Value="True" KeyTime="00:00:00"/>
</BooleanAnimationUsingKeyFrames>
<DoubleAnimation Duration="00:00:00.15"
Storyboard.TargetName="errorBorder"
Storyboard.TargetProperty="Opacity"
To="1"/>
<ThicknessAnimation Duration="00:00:00.15"
Storyboard.TargetName="errorBorder"
Storyboard.TargetProperty="Margin"
FillBehavior="HoldEnd"
From="1,0,0,0"
To="5,0,0,0">
<ThicknessAnimation.EasingFunction>
<BackEase EasingMode="EaseOut" Amplitude="2"/>
</ThicknessAnimation.EasingFunction>
</ThicknessAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="fadeInStoryboard"/>
<BeginStoryboard x:Name="fadeOutStoryBoard">
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="ErrorPopup"
Storyboard.TargetProperty="IsOpen">
<DiscreteBooleanKeyFrame Value="False" KeyTime="00:00:00"></DiscreteBooleanKeyFrame>
</BooleanAnimationUsingKeyFrames>
<DoubleAnimation Duration="00:00:00"
Storyboard.TargetName="errorBorder"
Storyboard.TargetProperty="Opacity"
To="0"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>然后,您可以将它设置为如下项目的ErrorTemplate:
<Style TargetType="TextBox">
<Setter Property="Validation.ErrorTemplate" Value="{StaticResource ErrorTemplate2}"/>
</Style>https://stackoverflow.com/questions/25037993
复制相似问题