user2079828
user2079828

Reputation: 655

C# WPF: Changing PlacementTarget of a ToolTip

I'm trying to change the PlacementTarget of a ToolTip to a window further up the visual tree in order to have custom ToolTip clipping effects in that window. I've hooked everything up except for the PlacementTarget. Here's an example from XAML and in code...neither work. This style is currently being used for a single tooltip attached to a TextBox.

<Style TargetType="ToolTip">
    <Setter Property="ToolTipService.PlacementTarget"
            Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, 
                AncestorType={x:Type Grid }} }" />
</Style>

If I go into code and look at the tooltip.PlacementTarget once it's attached to something...it's always set to the TextBox. I've tried multiple ways of using the VisualTree to get different UIElements. Nothing seems to work...so I'm assuming I'm not understanding or missing something.

The thing that really gets me is that if I go into my code and look at the PlacementTarget of the tooltip, it won't let me set it to anything else. For instance:

var ancestors = toolTip.PlacementTarget.GetSelfAndAncestors();

foreach(var ancestor in ancestors)
{
    if(var ancestor is Grid)
    {
        // Conditional always hits.
        // Before this line, PlacementTarget is a TextBox.
        toolTip.PlacementTarget = (UIElement)ancestor;  
        // After the line, PlacementTarget is still a TextBox.
    }
}

What am I doing incorrectly or not understanding?

Edit for Context: The custom clipping effect is to basically just find the closest ancestor window to the ToolTip's target and use that to make sure the ToolTip never goes outside the bounds of that window.

Upvotes: 2

Views: 4198

Answers (1)

Funk
Funk

Reputation: 11221

A short sample setting a Tooltip, using a property on the parent Window as PlacementTarget.

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Tag="Bar">
    <Window.Resources>
        <ToolTip x:Key="FooToolTip">
            <StackPanel>
                <TextBlock Text="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource AncestorType={x:Type ToolTip}}}"/>
            </StackPanel>
        </ToolTip>
    </Window.Resources>
    <Grid>
        <TextBlock 
            Text="Foo"
            ToolTip="{StaticResource FooToolTip}"
            ToolTipService.PlacementTarget="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
            HorizontalAlignment="Center" VerticalAlignment="Center" Height="20" Width="50">
        </TextBlock>
    </Grid>
</Window>

EDIT

To answer your questions,

the first snippet uses ToolTipService in the wrong way:

The ToolTipService class attached properties are used to determine the placement, behavior, and appearance of a tooltip. These properties are set on the element that defines the tooltip.

Applied in a style:

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        Tag="Bar">
    <Window.Resources>
        <ToolTip x:Key="FooToolTip">
            <StackPanel>
                <TextBlock Text="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource AncestorType={x:Type ToolTip}}}"/>
            </StackPanel>
        </ToolTip>
        <Style x:Key="ToolTipStyle">
            <Setter Property="ToolTipService.ToolTip" Value="{StaticResource FooToolTip}"/>
            <Setter Property="ToolTipService.PlacementTarget" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>
        </Style>
    </Window.Resources>
    <Grid>
        <TextBlock 
            Text="Foo" Style="{StaticResource ToolTipStyle}"
            HorizontalAlignment="Center" VerticalAlignment="Center" Height="20" Width="50">
        </TextBlock>
    </Grid>
</Window>

As for your second snippet in code behind, you can't set the PlacementTarget once the ToolTip is open and when the ToolTip is closed the PlacementTarget is null. As @mm8 pointed out, this has to do with the ToolTip and the PlacementTarget being in different visual trees, since a ToolTip spawns a Window of its own.

Upvotes: 4

Related Questions