WPF验证错误:使用错误消息设置工具提示

20

为什么错误没有提示文本?

<Style TargetType="{x:Type TextBox}">
    <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <StackPanel>
                    <Border ...>
                        <AdornedElementPlaceholder ... 
                            ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
                    </Border>
                    ...
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我也注意到了

<AdornedElementPlaceholder ...
    ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />

为什么下面的内容成功了,即使绑定相同,而上面的失败了?难道 AdornedElementPlaceholder 没有指向文本框吗? 即使它没有指向,难道不应该出现工具提示吗?

<Style.Triggers>
    <Trigger Property="Validation.HasError" Value="True">
        <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
    </Trigger>
</Style.Triggers>
3个回答

26

我知道我来得晚了,但让我分享一下我在研究这个问题时找到的解决方案:WPF自定义验证器和工具提示

在其最简单的形式中,此ErrorTemplate仅显示一个带有整个AdornedElementErrorContentTooltip

<ControlTemplate x:Key="validationTemplate">
    <Grid Background="Transparent"
          ToolTip="{Binding Path=/ErrorContent}">
        <AdornedElementPlaceholder />
    </Grid>
</ControlTemplate>

当然你可以按照自己的想法进行装饰,例如使用Tooltip来标记。

<ControlTemplate x:Key="validationTemplate">
    <Grid>
        <Ellipse Fill="Red" Opacity="0.8" Width="10" Height="10"
                 HorizontalAlignment="Right" VerticalAlignment="Top"
                 ToolTip="{Binding Path=/ErrorContent}" />
        <AdornedElementPlaceholder />
    </Grid>
</ControlTemplate>
将这个 Template 放置在 Resources 中,您只需要设置 Validation.ErrorTemplate
Validation.ErrorTemplate="{StaticResource validationTemplate}"

即使这个烦人的触发器也不再需要了。

<Style.Triggers>
    <Trigger Property="Validation.HasError" Value="True">
        <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
    </Trigger>
</Style.Triggers>

2
这是一个好主意;不幸的是,你的第一个解决方案会在整个文本框上放置一个(透明的)覆盖层,防止用户将其聚焦并更正错误。 - poke
@poke 你说得对。第一种解决方案只适用于显示错误的控件。但也许第二种解决方案是你想要的。 - LPL
第二种解决方案对于TextBox很好用,但对于ComboBox则不行。如果我将IsHitTestVisible设置为true,则根本无法单击ComboBox,而这似乎是使ToolTip正常工作所必需的。有什么想法吗? - Matt Zappitello
@MattZappitello 刚刚尝试了一下 ComboBox,没有任何问题(ToolTip 显示正常,无需进行任何代码更改)。我认为问题是在其他地方引起的。 - LPL
@LPL - 工具提示正常显示,但我无法单击ComboBox以使下拉列表出现。如果将IsHitTestVisible设置为false,则可以与ComboBox交互,但工具提示将不会显示。您能够与ComboBox交互并查看工具提示吗? - Matt Zappitello
@MattZappitello 是的,两者都是可用的。也许你的 validationTemplate Grid 继承了某个背景?你可以尝试将 Background 设置为 {x:Null} - LPL

6
您无法在AdornedElementPlaceholder上放置工具提示,我认为它根本不可见,它只是为使用它的人(在您的情况下为TextBox)保留空间。通过使用Snoop查看Visual Tree,我们可以看到TemplatedAdorner最终出现在VisualTree中的不同位置,因此我们将无法从VisualTree中找到TextBox。我们可以通过AdornedElement找到它,但仍然无法设置工具提示。
这里唯一可见的是Border。 Border知道它的Child- TemplatedAdorner,后者又知道它的AdornedElement- TextBox。因此,我们可以使用此方法为Border设置ToolTip。(但是,此绑定似乎无法更新边框的工具提示。当我使用Snoop查看它并在此之后显示时,它起作用。)
<Border BorderBrush="Red"
        BorderThickness="4"
        ToolTip="{Binding RelativeSource={RelativeSource self},
                  Path=Child.AdornedElement.(Validation.Errors)[0].ErrorContent}">

因此,TextBox具有其附加属性Validation,我们可以在其中找到ErrorContent,因此它必须设置自己的ToolTip,就像您在上一个示例中所做的那样,否则它将无法工作。

4
解决方案很好,但为了避免在您的Output.Debug窗口中出现异常,我建议将您的ToolTip绑定设置为ToolTip="{Binding RelativeSource={RelativeSource self}, Path=Child.AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}"。 - Dude0001

1
I found a way to implement ToolTip with the returned error message from the validation class that you might create to validate your input.

首先: 绑定错误消息

TextBox添加<Style>,并使用Style.Trigger,如下所示:

<Style TargetType="{x:Type TextBox}" x:Key="ToolTipError">
    <!-- Some style setters -->
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="true">
            <Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
        </Trigger>
    </Style.Triggers>
</Style>

第二步:将样式添加到TextBox
<TextBox 
    Style="{StaticResource ToolTipError}"
    Validation.ErrorTemplate="{StaticResource validationTemplate}">
    <TextBox.Text>
        <Binding 
            Path="YourViewModelProperty"
            UpdateSourceTrigger="PropertyChanged"
            ValidatesOnNotifyDataErrors="True"
            ValidatesOnDataErrors="True"
            NotifyOnValidationError="True">
            <Binding.ValidationRules>
                <ExceptionValidationRule:DateValidationRule ValidatesOnTargetUpdated="True"/>
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

奖励!

你可以用其他的东西来替换丑陋的红色边框。 例如,你可以将其更改为红色感叹号:

<Window.Resources>
    <ControlTemplate x:Key="validationTemplate">
        <StackPanel>
            <TextBlock Text="!" FontSize="26" Foreground="Red"/>
            <AdornedElementPlaceholder/>
        </StackPanel>
    </ControlTemplate>
<Window.Resources>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接