How to bind ToolTip content in a custom textblock styles property setter

1.3k Views Asked by At

I am trying to create a textblock that shows a tooltip of the textblock's text when its being trimmed. I have the actual visibility part of this taken care of in a converter. My problem is binding the ToolTip's content to its partent textblock's text. I have been fiddling with different relative paths for awhile now and can never get anything but a blank tooltip. The text shows up fine when I want if I hardcode something in the tooltips content.

<Style x:Key="InfoToolTipBaseTextBlockStyle" TargetType="{x:Type TextBlock}" BasedOn="{StaticResource TextBlockBase}">
    <Setter Property="ToolTip">
        <Setter.Value>
            <ToolTip Visibility="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget, Converter={StaticResource TrimmedVisibilityConverter}}" Content="{Binding Path=Text, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TextBlock}}}"/>                
        </Setter.Value>
    </Setter>
</Style>
2

There are 2 best solutions below

0
On

Solved it simply by this.

        <Style x:Key="InfoToolTipBaseTextBlockStyle" TargetType="{x:Type TextBlock}" BasedOn="{StaticResource TextBlockBase}">
            <Setter Property="ToolTip">
                <Setter.Value>
                    <ToolTip Visibility="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget, Converter={StaticResource TrimmedVisibilityConverter}}"
                             Content="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget.Text}"/>
                </Setter.Value>
            </Setter>
        </Style>
8
On

Instead of creating a tooltip that's always there, setting its content, and then switching its visibility, just have a style trigger on the TextBlock that sets the ToolTip property to Text when needed.

I've used your existing converter, but you might want to rewrite it to return bool. Then you'd have Value="True" in the DataTrigger.

<Style 
    x:Key="InfoToolTipBaseTextBlockStyle" 
    TargetType="{x:Type TextBlock}" 
    BasedOn="{StaticResource TextBlockBase}"
    >
    <Style.Triggers>
        <DataTrigger 
            Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource TrimmedVisibilityConverter}}"
            Value="Visible"
            >
            <Setter Property="ToolTip" Value="{Binding Text, RelativeSource={RelativeSource Self}}" />
        </DataTrigger>
    </Style.Triggers>
</Style>

I don't know if this is an issue for you, but if Text changes at runtime, the the tooltip won't be updated, because that Binding doesn't know you care about the Text property. The fix for that would be to rewrite the converter as IMultiValueConverter so you can use it with a MultiBinding that would have bindings to Text as well as Self. It wouldn't have to use Text, but it would update the target when Text changes.

A better solution, simpler and WPFish, would be to write a behavior for TextBlock that recycles the guts of your converter, handles change notifications on Text, and updates an attached TextBlockExt.IsTextElided bool property on the TextBlock.