Wpf 如何创建工具提示以显示单个控件的多个验证错误?

Wpf 如何创建工具提示以显示单个控件的多个验证错误?,wpf,xaml,validation,Wpf,Xaml,Validation,我试图通过控件上的工具提示来显示控件的多个验证错误,但没有找到实现这一点的方法 我可以通过以下样式的工具提示轻松显示控件的单个验证错误: <Style TargetType="TextBox"> <Style.Triggers> <Trigger Property="Validation.HasError" Value="True"> <Setter Property="ToolTi

我试图通过控件上的工具提示来显示控件的多个验证错误,但没有找到实现这一点的方法

我可以通过以下样式的工具提示轻松显示控件的单个验证错误:

<Style TargetType="TextBox">
        <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="True">
                <Setter Property="ToolTip" Value="{Binding Path=(Validation.Errors).CurrentItem.ErrorContent, RelativeSource={x:Static RelativeSource.Self}}"/>
            </Trigger>
        </Style.Triggers>
</Style>

但是,这种方法只允许我显示第一个验证错误。我尝试在工具提示中获取验证错误列表,但该列表从未显示。以下是我尝试过的方法:

在工具提示中放置ItemsControl,使用Validation.Errors作为ItemsSource,CurrentItem.ErrorContent作为要显示的文本:

<Style TargetType="TextBox">
        <Style.Triggers>
            <Trigger Property="Validation.HasError"
                     Value="True">
                <Setter Property="ToolTip">
                    <Setter.Value>
                        <ItemsControl>
                            <ItemsControl.ItemsSource>
                                <Binding Path="(Validation.Errors)" RelativeSource="{x:Static RelativeSource.Self}" />
                            </ItemsControl.ItemsSource>
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding CurrentItem.ErrorContent}" Foreground="Red"/>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </Setter.Value>
                </Setter>
            </Trigger>
        </Style.Triggers>
    </Style>
<Style TargetType="TextBox">
        <Style.Triggers>
            <Trigger Property="Validation.HasError"
                     Value="True">
                <Setter Property="ToolTip">
                    <Setter.Value>
                        <ItemsControl>
                            <ItemsControl.ItemsSource>
                                <Binding Path="(Validation.Errors).CurrentItem" RelativeSource="{x:Static RelativeSource.Self}" />
                            </ItemsControl.ItemsSource>
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding ErrorContent}" Foreground="Red"/>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </Setter.Value>
                </Setter>
            </Trigger>
        </Style.Triggers>
    </Style>

我还尝试使用Validation.Errors.CurrentItem作为ItemsSource,使用ErrorContent作为要显示的文本:

<Style TargetType="TextBox">
        <Style.Triggers>
            <Trigger Property="Validation.HasError"
                     Value="True">
                <Setter Property="ToolTip">
                    <Setter.Value>
                        <ItemsControl>
                            <ItemsControl.ItemsSource>
                                <Binding Path="(Validation.Errors)" RelativeSource="{x:Static RelativeSource.Self}" />
                            </ItemsControl.ItemsSource>
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding CurrentItem.ErrorContent}" Foreground="Red"/>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </Setter.Value>
                </Setter>
            </Trigger>
        </Style.Triggers>
    </Style>
<Style TargetType="TextBox">
        <Style.Triggers>
            <Trigger Property="Validation.HasError"
                     Value="True">
                <Setter Property="ToolTip">
                    <Setter.Value>
                        <ItemsControl>
                            <ItemsControl.ItemsSource>
                                <Binding Path="(Validation.Errors).CurrentItem" RelativeSource="{x:Static RelativeSource.Self}" />
                            </ItemsControl.ItemsSource>
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding ErrorContent}" Foreground="Red"/>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </Setter.Value>
                </Setter>
            </Trigger>
        </Style.Triggers>
    </Style>

任何这些方法都会导致显示空的工具提示:

我可以使用validation.ErrorTemplate将控件的验证错误列表显示为控件外部的列表:

<Style TargetType="TextBox">
        <Setter Property="Validation.ErrorTemplate">
            <Setter.Value>
                <ControlTemplate>
                    <StackPanel>
                        <AdornedElementPlaceholder/>
                        <ItemsControl ItemsSource="{Binding}">
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding ErrorContent}" Foreground="Red"/>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </StackPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

答案显示了如何使用ErrorTemplate将错误放置在单独的元素工具提示中。在ErrorTemplate中,您似乎可以访问完整的错误列表,而在工具提示样式中,您似乎没有我上面尝试过的错误列表。答案中的第一个解决方案使控件不可访问,这是我不想要的。我尝试了答案中的第二种解决方案:

<Style TargetType="TextBox">
        <Setter Property="Validation.ErrorTemplate">
            <Setter.Value>
                <ControlTemplate>
                    <Grid>
                        <Ellipse Fill="Red" Opacity="0.8" Width="10" Height="10" HorizontalAlignment="Right" VerticalAlignment="Top">
                            <Ellipse.ToolTip>
                                <ItemsControl ItemsSource="{Binding}">
                                    <ItemsControl.ItemTemplate>
                                        <DataTemplate>
                                            <TextBlock Text="{Binding ErrorContent}" Foreground="Red"/>
                                        </DataTemplate>
                                    </ItemsControl.ItemTemplate>
                                </ItemsControl>
                            </Ellipse.ToolTip>
                        </Ellipse>
                        <AdornedElementPlaceholder />
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

这确实为我提供了一个包含控件所有错误的工具提示:


但是,必须将鼠标悬停在红色圆圈上才能显示工具提示。我的目标是当您将鼠标悬停在控件上时显示工具提示,我认为这对用户来说会更直观。我似乎无法找到如何将多个错误放入实际控件工具提示中。这可能吗?

我知道这个问题在不久前发布了,但我也遇到了同样的问题,希望与大家分享我的解决方案(希望它能帮助其他人;)

在谷歌搜索了一段时间后,我找到了一个描述这个问题的方法。他们建议用多重绑定解决这个问题,我就是这么做的。我只用了一种风格来做这件事
下面是样式的代码:

<Style TargetType="TextBox">
        <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="true">
                <Setter Property="BorderBrush" Value="Red" /> 
                <Setter Property="ToolTip">
                    <Setter.Value>
                        <MultiBinding Converter="{StaticResource conv}">
                            <Binding RelativeSource="{RelativeSource Self}" Path="(Validation.Errors)" />
                            <Binding RelativeSource="{RelativeSource Self}" Path="(Validation.Errors).Count" />
                        </MultiBinding>
                    </Setter.Value>
                </Setter>
            </Trigger>
        </Style.Triggers>
    </Style>

问题是(Validation.Errors)会为您获取一个ReadOnlyObservableCollection,并且该集合将随着时间的推移而填充。但是当您绑定到(Validation.Errors)时,它只会注意到第一项。这就是第二个绑定(Validation.Errors)的原因。计数,这样每次更改计数时,都会调用转换器。
现在,我们需要转换器:

public class MultiLineConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (!(values[0] is IEnumerable<ValidationError>))
            return null;

        var val = values[0] as IEnumerable<ValidationError>;

        string retVal = "";

        foreach (var itm in val)
        {
            if (retVal.Length > 0)
                retVal += "\n";
            retVal += itm.ErrorContent;

        }
        return retVal;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
public类multileconverter:IMultiValueConverter
{
公共对象转换(对象[]值,类型targetType,对象参数,CultureInfo区域性)
{
如果(!(值[0]是IEnumerable))
返回null;
var val=值[0]为IEnumerable;
字符串retVal=“”;
foreach(var itm以val为单位)
{
如果(retVal.Length>0)
retVal+=“\n”;
retVal+=itm.ErrorContent;
}
返回返回;
}
公共对象[]转换回(对象值,类型[]目标类型,对象参数,CultureInfo区域性)
{
抛出新的NotImplementedException();
}
}
它仅使用值[0],因为该值是集合。然后,它将为所有ErrorContents创建一个字符串


希望这能有所帮助。

这已经很旧了,但我在这方面已经坚持了一段时间,amd找到了一种我更喜欢的方式。 它不会将验证错误转换为字符串,而是使用ItemsControl,这对我来说更有意义

工具提示不是窗口视觉树的一部分,但您仍然可以为其创建样式<代码>验证。错误
验证错误
对象的集合

<Style x:Key="validationTooltipStyle" TargetType="{x:Type ToolTip}">
            <Setter Property="DataContext" Value="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget}"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ToolTip">
                        <ItemsControl ItemsSource="{Binding Path=(Validation.Errors)}" Background="#FFDC000C" Margin="0 0 3 0">
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding ErrorContent}" Foreground="#FFFFFF"/>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
</Style>

实例化工具提示资源

<ToolTip x:Key="validationTooltip" Style="{StaticResource validationTooltipStyle}"/>