我有多个控件,包括TextBox和ComboBox,我希望所有这些控件都显示一个ToolTip,其中包含Validation.Errors集合中包含的所有错误。如果可能的话,我希望他们都能分享一种共同的风格,这就是我的努力。我确信我在ToolTip setter中的绑定有问题,但我无法弄清楚是什么。我在INotifyDataErrorInfo实现中返回一个Error对象,它指定错误的严重性(错误或警告)。
我希望有一个适用于Window中所有控件的样式,它会显示一个ToolTip,其中包含该控件的所有错误和警告的列表。错误应显示为红色,警告显示为黄色。这是我提出的风格:
<Style TargetType="FrameworkElement">
<Setter Property="ToolTip">
<Setter.Value>
<ItemsControl ItemsSource="{Binding Path=(Validation.Errors), RelativeSource={RelativeSource Self}}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ErrorContent.ErrorMessage}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Red"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ErrorContent.ErrorSeverity}"
Value="{x:Static local:ErrorType.Warning}">
<Setter Property="Foreground" Value="Yellow"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(Validation.HasError)}" Value="True">
<Setter Property="ToolTip">
<Setter.Value>
<ItemsControl ItemsSource="{Binding Path=(Validation.Errors)}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ErrorContent.ErrorMessage}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Red"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ErrorContent.ErrorSeverity}"
Value="{x:Static local:ErrorType.Warning}">
<Setter Property="Foreground" Value="Yellow"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
我尝试更改RelativeSource以在AncestorLevel 1和2中搜索AncestoryType of Control。这些似乎都不起作用。
我将这个样式基于我用于ErrorTemplate的ControlTemplate,它几乎完全相同:它根据错误的严重程度显示红色或黄色边框,并显示与我想要为ToolTip做的完全相同的工具提示在控制本身。我确定它与我的绑定有关,因为ErrorTemplate自动将其DataContext设置为Validation.Errors集合,这使得为ItmesCollection绑定ItemsSource变得容易。风格的工具提示没有这样的运气。这是我用于ErrorTemplate的工作ControlTemplate:
<ControlTemplate x:Key="ErrorTemplate">
<Border BorderThickness="1">
<AdornedElementPlaceholder Name="ElementPlaceholder"/>
<Border.Style>
<Style TargetType="Border">
<Setter Property="BorderBrush" Value="Red"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ElementPlaceholder, Path=AdornedElement.(Validation.Errors)[0].ErrorContent.ErrorSeverity}"
Value="{x:Static local:ErrorType.Warning}">
<Setter Property="BorderBrush" Value="Yellow"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Border.ToolTip>
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ErrorContent.ErrorMessage}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Red"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ErrorContent.ErrorSeverity}"
Value="{x:Static local:ErrorType.Warning}">
<Setter Property="Foreground" Value="Yellow"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border.ToolTip>
</Border>
</ControlTemplate>
有人能给我任何建议吗?
答案 0 :(得分:7)
这可以更容易实现。
如果您将绑定写入&#34; Tooltip&#34;如上所述:
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors), Converter={StaticResource ErrorCollectionConverter}}">
</Setter>
</Trigger>
The Binding&#34;奇迹般地&#34;实际上将自己重新绑定到&#34; PlacementTarget&#34;工具提示。因此,对照它是附加的。
如果您需要显示完整的项目列表,可以执行以下操作:
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip DataContext="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget}">
<ItemsControl ItemsSource="{Binding Path=(Validation.Errors)}" DisplayMemberPath="ErrorContent" />
</ToolTip>
</Setter.Value>
</Setter>
</Trigger>
您甚至可以删除Tooltip对象并直接从ItemsControl绑定到PlacementTarget。然后在ItemsControl上通过AncestorType使用Tooltip作为RelativeSource。
希望这会有所帮助:)
答案 1 :(得分:5)
在试图解决这个问题很长一段时间之后,我终于偶然发现post on the MSDN forums导致我走上了正确的道路。首先,我需要为我想要的每个TargetType指定样式并将它们基于原始样式。其次,我意识到问题不在于我的绑定,而在于绑定的集合没有被更新。我不知道为什么我的ListBox / ItemsControl在XAML中指定时没有更新,但如果你在转换器中指定它,它确实有效。这是我的新风格:
<Style TargetType="Control" x:Key="ErrorToolTip">
<Style.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBlock Text="{Binding ErrorContent.ErrorMessage}"
Background="Transparent">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Red"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ErrorContent.ErrorSeverity}"
Value="{x:Static local:ErrorType.Warning}">
<Setter Property="Foreground" Value="Orange" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors), Converter={StaticResource ErrorCollectionConverter}}">
</Setter>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="TextBox" BasedOn="{StaticResource ErrorToolTip}"/>
<Style TargetType="ComboBox" BasedOn="{StaticResource ErrorToolTip}"/>
这是我的转换器功能:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return null;
return new ListBox
{
ItemsSource = (ReadOnlyObservableCollection<ValidationError>) value,
BorderThickness = new Thickness(0),
Background = Brushes.Transparent
};
}
我希望这对那些遇到同样问题的人有帮助。如果有人知道为什么会产生这么大的差异,我很想知道。
答案 2 :(得分:1)
这只是我使用的Matts答案的更简化版本。它仅适用于TextBox
类型的控件,并且不使用错误严重性。
当我需要在用户输入的目录路径的上下文中显示一个或多个错误时,我使用了一个案例。与我使用的Matts答案形成鲜明对比
DisplayMemberPath =“ErrorContent”
直接在转换器中访问错误。
当附加属性TextBox
为真时,显示工具提示的Validation.HasError
样式:
<UserControl.Resources>
<ui:ErrorCollectionConverter x:Key="ErrorCollectionConverter"></ui:ErrorCollectionConverter>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors), Converter={StaticResource ErrorCollectionConverter}}">
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
我的“目录”TextBox
隐式使用样式:
<TextBox Text="{Binding Directory, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True}"></TextBox>
直接访问ErrorContent
属性的值转换器:
internal class ErrorCollectionConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return null;
return new ListBox
{
ItemsSource = (ReadOnlyObservableCollection<ValidationError>)value,
BorderThickness = new Thickness(0),
Background = Brushes.Transparent,
DisplayMemberPath = "ErrorContent"
};
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}