2017-06-16 83 views
2

我试图将工具提示的PlacementTarget更改为视觉树上的一个窗口,以便在该窗口中具有自定义工具提示裁剪效果。除了PlacementTarget之外,我已经吸引了所有人。这里有一个来自XAML和代码的例子......都不起作用。此样式当前正在用于连接到TextBox的单个工具提示。C#WPF:更改工具提示的PlacementTarget

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

如果我进入代码,并期待在tooltip.PlacementTarget一旦它的附加的东西......它总是设置为文本框。我尝试过使用VisualTree获取不同UIElements的多种方式。似乎没有任何工作......所以我假设我不理解或错过某些东西。

真正让我感到意外的是,如果我进入我的代码并查看工具提示的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. 
    } 
} 

我在做什么不正确或不理解?

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

+0

WPF的工具提示与PlacementTarget和DataContext一起工作的方式有些杂乱。它获得配置快速使用;看看在https://stackoverflow.com/questions/6783693/how-to-set-a-placementtarget-for-a-wpf-tooltip-without-messing-up-the-datacontex –

+0

你的视觉树如何定义?工具提示驻留在自己的可视化树中,并且无法使用RelativeSource在父窗口中查找某些内容。 – mm8

+0

@TimothyGroote谢谢,我会检查出来。对于mm8,我认为RelativeSource值首先会定位到默认目标(在这种情况下是TextBox),然后向上移动它们的可视化树来查找第一个Grid(可能需要将AnscestorLevel设置为1)。但是,无论如何,我无法真正设置PlacementTarget。 – user2079828

回答

2

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

编辑

回答您的问题,

的第一个片段以错误的方式使用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> 

至于在代码中你的第二个片段背后,你不能设置PlacementTarget一旦ToolTip是开放的,当ToolTip关闭时PlacementTarget为null 。正如@ mm8所指出的那样,这与ToolTipPlacementTarget处于不同的视觉树中有关,因为ToolTip产生自己的和Window

+0

我见过这个,它(可能)解决了我的问题,但并没有真正回答这个问题。这两个代码片段究竟有什么不正确?为什么我不能在第二个程序中以编程方式设置PlacementTarget? – user2079828

+0

此外,它需要在工具提示样式中设置,因为我没有将placementTarget放置在我希望样式使用的每个控件中。 – user2079828

+0

我用你的解释让我走了。我能够通过创建一个行为的子类来解决它,它将xaml中的属性附加到任何给定的行为(基于https://stackoverflow.com/questions/1647815/how-to-add-a-blend-behavior -in-A-风格引领者)。然后我在窗口上放置一个标签,并使用我的行为设置工具提示样式。它搜索与标签匹配的第一个祖先,并使用其属性来适应弹出窗口。这允许我为每个视图设置一个工具提示样式,并将标签放置在我希望工具提示适合的窗口上。不需要单独控制。 – user2079828