WPF - TextBlock 中使用 TextBlock 中的文本 属性 的工具提示

WPF - ToolTip in TextBlock that use the Text Property from the TextBlock

我们的应用程序中有很多 TextBlock,其中许多必须有工具提示。
通常,工具提示应显示与 TextBlock.Text 属性.
相同的内容 此外,如果 TextBlock.Text = ""null.

,则不应显示工具提示

所以我们在很多地方都有这个解决方案:

<TextBlock Text="{Binding SomeTextProperty}">
    <TextBlock.ToolTip>
        <ToolTip Visibility="{Binding SomeTextProperty}, Converter={StaticResource StringToVisibilityConverter}">
            <TextBlock Text="{Binding SomeTextProperty}" />
    </TextBlock.ToolTip>
</TextBlock>

通知:

所以我尝试为 TextBlocks 发明一种样式,它使用 BindingsRelativeSource 来获得工具提示的 TextBlock.Text 属性。我想到了这个解决方案:

主要Window(或多或少复制粘贴)

<Window x:Class="Main.Views.ToolTips"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Main.Views"
        xmlns:converters="clr-namespace:Main.Converters"
        mc:Ignorable="d"
        Title="ToolTips" Height="450" Width="800">

    <Window.Resources>
        <Style TargetType="TextBlock" x:Key="TextBlockWithToolTipStyle">
            <Style.Resources>
                <converters:StringToVisibilityConverter x:Key="StringToVisibilityConverter" />
            </Style.Resources>
            <Setter Property="ToolTip">
                <Setter.Value>
                    <ToolTip Visibility="{Binding Text, RelativeSource={RelativeSource AncestorType={x:Type TextBlock}}, Converter={StaticResource StringToVisibilityConverter}}">
                        <ToolTip.Content>
                            <TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type TextBlock}}}" />
                        </ToolTip.Content>
                    </ToolTip>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

    <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">

        <TextBlock Text="This should display a tooltip" />
        <TextBlock Text="asdf" 
                   Background="Gray"
                   Style="{StaticResource TextBlockWithToolTipStyle}" />

        <Separator Height="50" Visibility="Hidden" />

        <TextBlock Text="This should not display a tooltip" />
        <TextBlock Text="" 
                   Background="LightGray"
                   Style="{StaticResource TextBlockWithToolTipStyle}" />
    </StackPanel>
</Window>

StringToVisibilityConverter

public class StringToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var input = value is null ? string.Empty : value.ToString();
        return string.IsNullOrWhiteSpace(input) ? Visibility.Collapsed : Visibility.Visible;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

这当然不行!
我在 StringToVisibilityConverter 中放置了一个断点,当我将两个 TextBlocks 悬停在 Window.

中时,该断点没有命中

在 VS 的 XAML Binding Failures 视图中,我看到两个关于 ToolTip.VisibilityTextBlock.Text 的绑定错误:

这个可以解决吗?
如果是,怎么做?

/BR, 史蒂夫

ToolTip 不是可视化树的一部分。这就是您的 Binding.RelativeSource 无法解析的原因。

要引用由 ToolTip 修饰的元素,您必须引用 ToolTip.PlacementTarget 属性:

<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=ToolTip}, Path=PlacementTarget.Text}" />

此外,您不应尝试切换 ToolTip.Visibility。它不会工作。 而是使用 Trigger 来设置 ToolTip.

正确的解法如下:

<Style TargetType="TextBlock"
       x:Key="TextBlockWithToolTipStyle">
  <Style.Resources>
    <ToolTip x:Key="ToolTip">
      <TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=ToolTip}, Path=PlacementTarget.Text}" />
    </ToolTip>
  </Style.Resources>

  <Setter Property="ToolTip"
          Value="{StaticResource ToolTip}" />

  <Style.Triggers>
    <Trigger Property="Text" Value="">
      <Setter Property="ToolTip" Value="{x:Null}" />
    </Trigger>
  </Style.Triggers>
</Style>