如何在silverlight TextBlock上显示验证错误

本文关键字:显示 验证 错误 TextBlock silverlight | 更新日期: 2023-09-27 18:30:11

我有一个表示XML文档的树。我展示了使用实现INotifyDataErrorInfo的绑定类的XML验证错误。

它在文本框或组合框等可编辑控件上运行良好。

但有些节点只是文本块。他们也有错误。

我该怎么做?

如何在silverlight TextBlock上显示验证错误

我建议您将TextBlock包装在ValidationErrorBorder:中

<ValidationErrorBorder DataContextValidationTargetPath="MyTextProperty">
    <TextBlock Text="{Binding Path=MyTextProperty}"/>
</ValidationErrorBorder>

验证错误边境管制代码:

/*
 * Use in conjuction with other Controls that do not have the appropriate
 * visualStates to indicate ValidationErrors.
 * Either set DataContextValidationTargetPath to have this
 * ValidationErrorBorder show validation errors that occur at the targeted
 * property of the DataContext
 * or bind ValidationTarget to any target you wish to have this
 * ValidationErrorBorder show validation errors occuring for the bound target.
 */
[TemplateVisualState(GroupName="ValidationStates", Name = "Valid")]
[TemplateVisualState(GroupName="ValidationStates", Name = "InvalidUnfocused")]
[TemplateVisualState(GroupName="ValidationStates", Name = "InvalidFocused")]
public class ValidationErrorBorder : ContentControl
{
    public object ValidationTarget
    {
        get { return GetValue( ValidationTargetProperty ); }
        set { SetValue( ValidationTargetProperty, value ); }
    }
    public static readonly DependencyProperty ValidationTargetProperty =
        DependencyProperty.Register( "ValidationTarget", typeof( object ),
        typeof( ValidationErrorBorder ), new PropertyMetadata( null ) );
    public string DataContextValidationTargetPath
    {
        get
        {
          return (string) GetValue( DataContextValidationTargetPathProperty );
        }
        set { SetValue( DataContextValidationTargetPathProperty, value ); }
    }
    public static readonly DependencyProperty
        DataContextValidationTargetPathProperty =
        DependencyProperty.Register( "DataContextValidationTargetPath",
        typeof( string ), typeof( ValidationErrorBorder ),
        new PropertyMetadata( null, HandlePathChanged ) );
    private static void HandlePathChanged(DependencyObject d,
        DependencyPropertyChangedEventArgs e)
    {
        ((ValidationErrorBorder) d).HandlePathChanged();
    }
    private void HandlePathChanged()
    {
        if (DataContextValidationTargetPath != null)
            SetBinding(ValidationTargetProperty,
                new Binding(DataContextValidationTargetPath));
        else
            ClearValue( ValidationTargetProperty );
    }
    public ValidationErrorBorder()
    {
        DefaultStyleKey = typeof( ValidationErrorBorder );
    }
}

控制模板:

<Style TargetType="controls:ValidationErrorBorder">
    <Setter Property="IsTabStop" Value="False"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="controls:ValidationErrorBorder">
                <Grid x:Name="RootElement" Background="{x:Null}">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="ValidationStates">
                            <VisualState x:Name="Valid"/>
                            <VisualState x:Name="InvalidUnfocused">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ValidationErrorElement">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="InvalidFocused">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ValidationErrorElement">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Visible</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen" Storyboard.TargetName="validationTooltip">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <system:Boolean>True</system:Boolean>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Grid>
                        <ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" />
                        <Border x:Name="ValidationErrorElement" BorderBrush="#FFDB000C" BorderThickness="1" CornerRadius="1" Visibility="Collapsed">
                            <ToolTipService.ToolTip>
                                <ToolTip x:Name="validationTooltip" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}" Template="{StaticResource ValidationToolTipTemplate}">
                                    <ToolTip.Triggers>
                                        <EventTrigger RoutedEvent="Canvas.Loaded">
                                            <BeginStoryboard>
                                                <Storyboard>
                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsHitTestVisible" Storyboard.TargetName="validationTooltip">
                                                        <DiscreteObjectKeyFrame KeyTime="0">
                                                            <DiscreteObjectKeyFrame.Value>
                                                                <system:Boolean>True</system:Boolean>
                                                            </DiscreteObjectKeyFrame.Value>
                                                        </DiscreteObjectKeyFrame>
                                                    </ObjectAnimationUsingKeyFrames>
                                                </Storyboard>
                                            </BeginStoryboard>
                                        </EventTrigger>
                                    </ToolTip.Triggers>
                                </ToolTip>
                            </ToolTipService.ToolTip>
                            <Grid Background="Transparent" HorizontalAlignment="Right" Height="12" Margin="1,-4,-4,0" VerticalAlignment="Top" Width="12">
                                <Path Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 z" Fill="#FFDC000C" Margin="1,3,0,0"/>
                                <Path Data="M 0,0 L2,0 L 8,6 L8,8" Fill="#ffffff" Margin="1,3,0,0"/>
                            </Grid>
                        </Border>
                    </Grid>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

和validationTooltipTemplate:

<ControlTemplate x:Key="ValidationToolTipTemplate">
    <Grid x:Name="Root" Margin="5,0" Opacity="0" RenderTransformOrigin="0,0">
        <Grid.RenderTransform>
            <TranslateTransform x:Name="xform" X="-25"/>
        </Grid.RenderTransform>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="OpenStates">
                <VisualStateGroup.Transitions>
                    <VisualTransition GeneratedDuration="0"/>
                    <VisualTransition GeneratedDuration="0:0:0.2" To="Open">
                        <Storyboard>
                            <DoubleAnimation Duration="0:0:0.2" To="0" Storyboard.TargetProperty="X" Storyboard.TargetName="xform">
                                <DoubleAnimation.EasingFunction>
                                    <BackEase Amplitude=".3" EasingMode="EaseOut"/>
                                </DoubleAnimation.EasingFunction>
                            </DoubleAnimation>
                            <DoubleAnimation Duration="0:0:0.2" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root"/>
                        </Storyboard>
                    </VisualTransition>
                </VisualStateGroup.Transitions>
                <VisualState x:Name="Closed">
                    <Storyboard>
                        <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root"/>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="Open">
                    <Storyboard>
                        <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="X" Storyboard.TargetName="xform"/>
                        <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root"/>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Border Background="#052A2E31" CornerRadius="5" Margin="4,4,-4,-4"/>
        <Border Background="#152A2E31" CornerRadius="4" Margin="3,3,-3,-3"/>
        <Border Background="#252A2E31" CornerRadius="3" Margin="2,2,-2,-2"/>
        <Border Background="#352A2E31" CornerRadius="2" Margin="1,1,-1,-1"/>
        <Border Background="#FFDC000C" CornerRadius="2"/>
        <Border CornerRadius="2">
            <TextBlock Foreground="White" MaxWidth="250" Margin="8,4,8,4" TextWrapping="Wrap" Text="{Binding (Validation.Errors)[0].ErrorContent}" UseLayoutRounding="false"/>
        </Border>
    </Grid>
</ControlTemplate>

默认情况下,Silverlight并不真正支持它。在过去,我发现一种行之有效的方法是制作一个从Textblock继承的控件。然后,您可以处理IDatanotify接口和异常,并在此基础上关闭不同颜色的文本块。