WPF显示带有验证错误消息的TextBlock,控件下方。

14

有没有一种方式可以在文本块下方显示错误内容,类似于以下代码将工具提示设置为包含错误文本的方式?

        <Style x:Key="textBoxInError" TargetType="Control">
        <Setter Property="Validation.ErrorTemplate">
            <Setter.Value>
                <ControlTemplate>
                    <DockPanel>
                        <TextBlock DockPanel.Dock="Left" Foreground="Red" FontWeight="Bold">*</TextBlock>
                        <TextBlock Text="WOULD LIKE TO SHOW WHAT TOOLTIP IS SHOWING" DockPanel.Dock="Bottom" Foreground="Red"/>
                        <Border BorderBrush="Red" BorderThickness="2">
                            <AdornedElementPlaceholder/>
                        </Border>
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <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>

换句话说,我更愿意在控件下方的 TextBlock 中显示错误消息,而不是在工具提示中显示。


我遇到的问题是,错误消息文本块将呈现在可能位于其下方的其他控件之上。它不会将所有内容下移以为其腾出空间。这可能与错误模板显示在修饰层上有关...还没有完全弄清楚。 - statikuz
2个回答

22

错误模板(ErrorTemplate)的 DataContext 已经是 Validation.Errors 的值,因此您只需执行以下操作:

<TextBlock Text="{Binding [0].ErrorContent}" DockPanel.Dock="Bottom" Foreground="Red"/>
或者
<TextBlock Text="{Binding ErrorContent}" DockPanel.Dock="Bottom" Foreground="Red"/>

0
我曾经也遇到过这个问题,但是我在 Stack Overflow 上找到的所有答案都使用了 "Validation.ErrorTemplate" 属性,不幸的是,这会在单独的 UI 层上呈现,这意味着父控件不会像 @statikuz 提到的那样调整其内容并隐藏后续控件,或者根本不够通用。
最终,我采用了以下解决方案:
<Style x:Key="hiddenTextblockErrorText" TargetType="TextBlock">
    <Setter Property="Visibility" Value="Collapsed"/>
    <Setter Property="Foreground" Value="DarkRed"/>
    <Setter Property="TextWrapping" Value="Wrap"/>
    <Setter Property="Text" Value="{Binding RelativeSource={RelativeSource Self}, Path=Tag.(Validation.Errors)/ErrorContent}"/>
    <Style.Triggers>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Tag.(Validation.HasError)}" Value="True">
            <Setter Property="Visibility" Value="Visible" />
        </DataTrigger>
    </Style.Triggers>
</Style>

你可以像这样使用它:

<TextBox Name="someField" Height="20">
    <TextBox.Text>
    <Binding Path="SomeProperty" Mode="TwoWay"UpdateSourceTrigger="PropertyChanged">
        <Binding.ValidationRules>
            <local:IsRequired/>
        </Binding.ValidationRules>
    </Binding>
</TextBox.Text>
</TextBox>
<TextBlock Tag="{Binding ElementName=someField}" Style="{StaticResource hiddenTextblockErrorText}"/>

所以你基本上只需要将你的字段绑定到错误的属性,然后你就可以从那里使用它来获取(Validation.Errors)附加属性。 请注意,你会收到一个无害的警告“属性Errors不能附加到类型为Object的元素”,但它完全正常工作(我找不到如何在这里进行转换)。

或者你可以使用一个LabelTarget属性代替Tag,这样你就不会收到任何警告,但是你会失去TextWrapping功能,除非你还覆盖模板,这样就有点冗长了:

<Style x:Key="hiddenLabelErrorText" TargetType="Label">
        <Setter Property="Visibility" Value="Collapsed"/>
        <Setter Property="Foreground" Value="DarkRed"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Label}">
                    <TextBlock TextWrapping="Wrap" Text="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType={x:Type Label}}, 
                        Path=Target.(Validation.Errors)/ErrorContent}"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Target.(Validation.HasError)}" Value="True">
                <Setter Property="Visibility" Value="Visible" />
            </DataTrigger>
        </Style.Triggers>
</Style>

<Label Target="{Binding ElementName=someField}" Style="{StaticResource hiddenLabelErrorText}"/>

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