【问题标题】:C# WPF: Changing PlacementTarget of a ToolTipC# WPF:更改工具提示的 PlacementTarget
【发布时间】:2017-06-16 06:11:50
【问题描述】:

我正在尝试将 ToolTip 的 PlacementTarget 更改为视觉树更上方的窗口,以便在该窗口中具有自定义 ToolTip 剪辑效果。除了 PlacementTarget 之外,我已经连接了所有东西。这是来自 XAML 和代码中的示例......两者都不起作用。此样式当前用于附加到 TextBox 的单个工具提示。

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

如果我进入代码并查看 tooltip.PlacementTarget 一旦它附加到某个东西......它总是设置为 TextBox。我尝试了多种使用 VisualTree 来获取不同 UIElement 的方法。似乎没有任何效果......所以我假设我没有理解或遗漏什么。

真正让我着迷的是,如果我进入我的代码并查看工具提示的 PlacementTarget,它不会让我将其设置为其他任何内容。例如:

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.
    }
}

我做错了什么或不理解?

编辑上下文:自定义剪辑效果基本上只是找到最接近工具提示目标的祖先窗口,并使用它来确保工具提示永远不会超出该窗口的范围。

【问题讨论】:

  • WPF 的工具提示使用 PlacementTargetDataContext 的方式有点混乱。它可以快速配置;看看stackoverflow.com/questions/6783693/…
  • 你的可视化树是如何定义的? Tooltip 位于其自己的可视化树中,无法使用 RelativeSource 在父窗口中查找内容。
  • @TimothyGroote 谢谢,我去看看。对于 mm8,我认为 RelativeSource 值将首先定位默认目标(在本例中为 TextBox)并向上移动它们的可视化树以找到第一个 Grid(但也许我需要将 AnscestorLevel 设置为 1)。但是,无论如何,我无法获得任何值来实际设置 PlacementTarget。

标签: c# wpf xaml


【解决方案1】:

设置Tooltip 的简短示例,使用父级Window 上的属性作为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>

编辑

回答你的问题,

第一个 sn-p 错误地使用了ToolTipService

ToolTipService 类的附加属性用于确定工具提示的位置、行为和外观。 这些属性设置在定义工具提示的元素上。

应用于样式:

<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>

至于后面代码中的第二个 sn-p,一旦 ToolTip 打开并且 ToolTip 关闭时 PlacementTarget 为空,您将无法设置 PlacementTarget。正如@mm8 所指出的,这与ToolTipPlacementTarget 位于不同的视觉树中有关,因为ToolTip 产生 一个自己的Window

【讨论】:

  • 我看过这个,它(可能)解决了我的问题,但并没有真正回答问题。两个代码 sn-ps 到底有什么不正确的地方?为什么我不能在第二个中以编程方式设置 PlacementTarget?
  • 另外,它需要设置为工具提示样式,因为我没有将placementTarget 放在我希望使用该样式的每个控件中。
  • 我用你的解释让我继续前进。我能够通过为 Behavior 创建一个子类来解决它,它将 xaml 中的属性附加到任何给定的行为(基于stackoverflow.com/questions/1647815/…)。然后我在窗口上放置一个标签并使用我的行为设置工具提示样式。它搜索与标签匹配的第一个祖先,并使用其属性来适应弹出窗口。这允许我为每个视图设置一种工具提示样式,并将标签放置在我希望工具提示适合的窗口上。不需要在单个控件中进行任何操作。
  • 我接受了你的回答,因为它解释了为什么我所做的事情不起作用。
猜你喜欢
  • 2011-10-10
  • 2011-10-02
  • 2011-06-23
  • 1970-01-01
  • 2010-10-22
  • 2011-10-02
  • 2011-06-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多