WPF:自定义工具提示箭头位置

9

我有一个自定义的工具提示样式,基本上创建了一个漂亮的黑色工具提示,带有指向您悬停在的项目位置的箭头。

问题是有时候工具提示不会始终放置在正确的位置(即靠近窗口边缘),这意味着工具提示箭头不再指向正确的位置... 有没有办法解决这个问题?或者我可以为每个位置创建特定的样式吗?

<Style x:Key="{x:Type ToolTip}" TargetType="ToolTip">
    <Setter Property="OverridesDefaultStyle" Value="true"/>
    <Setter Property="HasDropShadow" Value="True"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ToolTip">
                <StackPanel>
                    <Border CornerRadius="3" HorizontalAlignment="Center" VerticalAlignment="Top" Padding="10,7" BorderThickness="0" Background="#e5323232">
                        <StackPanel>
                            <TextBlock FontFamily="Arial" FontSize="12" Text="{TemplateBinding Content}" Foreground="#f0f0f0" />
                        </StackPanel>
                    </Border>
                    <Path Margin="10,0,0,0" Fill="#e5323232" Data="M 0 0 L 6 6 L 12 0 Z"/>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>

您需要将工具提示放置在哪里,是在鼠标光标上还是控件中心? - sa_ddam213
我希望箭头在水平方向上放置在不同的位置,以便它始终指向具有工具提示的控件/文本的中心。 - Chris
@Chris 这与所示用例类似 http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/4c6d216a-0011-4202-aa7e-2fccef3cc355 那个线程中的问题可以通过找到的解决方法来解决 http://stackoverflow.com/questions/15110410/determining-which-custompopupplacement-was-used-for-wpf-popup - Viv
@Viv 有趣的链接,但它并没有展示他是如何让自定义放置方式起作用的 - 你有什么想法吗? - Chris
@Chris 你有看 SO 评论中的第二个链接吗?我提出了一个“创意”解决方案来解决何时显示哪个箭头的问题。 - Viv
是的,我做了,只是那些代码之间的部分我不太确定... - Chris
2个回答

1
也许你可以尝试这个,我只是将Placement设置为Center并添加了一个HorizontalOffset以匹配你在模板中创建的箭头。
然而,这不会使其在控件的垂直方向上居中,所以你可以创建一个IValueConverter来计算控件的大小并除以2,或者你可以向你的StackPanel添加一个与边框大小相同的虚拟元素,这样就可以在不需要任何代码后台的情况下居中ToolTip。
<Style TargetType="{x:Type ToolTip}">
        <Setter Property="OverridesDefaultStyle" Value="true"/>
        <Setter Property="HasDropShadow" Value="True"/>
        <Setter Property="Placement" Value="Center" />
        <!--Offset to the arrow path-->
        <Setter Property="HorizontalOffset" Value="15"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ToolTip}">
                    <StackPanel>
                        <Border x:Name="border" CornerRadius="3" HorizontalAlignment="Center" VerticalAlignment="Top" Padding="10,7" BorderThickness="0" Background="#e5323232">
                            <StackPanel>
                                <TextBlock FontFamily="Arial" FontSize="12" Text="{TemplateBinding Content}" Foreground="#f0f0f0" />
                            </StackPanel>
                        </Border>
                        <Path Margin="10,0,0,0" Fill="#e5323232" Data="M 0 0 L 6 6 L 12 0 Z"/>

                        <!--Dummy rectangle same height as tool tip, so it centers on the control-->
                        <Rectangle Height="{Binding ActualHeight, ElementName=border}" />
                    </StackPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

嗨,谢谢你的回答,但这似乎没有改变任何东西?我错过了什么吗? - Chris

0
最简单的方法是使用控件树中存在的UIElement作为Tooltip的PlacementTarget。这样可以避免在接近窗口边缘时Silverlight自动定位的问题。
          <StackPanel ToolTipService.ToolTip="{Binding Title, Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"
                        ToolTipService.Placement="Bottom"
                        ToolTipService.PlacementTarget="{Binding ElementName=LayoutRoot}">                  
                <TextBlock Text="{Binding Title,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
          </StackPanel>

在这种情况下,工具提示将始终定位在LayoutRoot元素的起点。如果您有固定的路径大小,并且放置目标始终相对于要显示工具提示的控件处于相同位置,则可以正常工作。
如果您需要将工具提示相对于触发工具提示的控件定位,则必须使路径数据动态,并计算距离以在每次打开工具提示时在工具提示控件中创建新的路径数据。 针对这种情况,您必须处理Tooltip.IsOpened事件并实现此逻辑。如果您使用PlacementTarget,则始终知道相对于您的控件的方向,因此这使得计算路径顶点更容易。
另一种方式是实现自己的弹出窗口,当您将鼠标移动到控件上方时会显示它。您需要实现一些计算来获得弹出窗口相对于控件的位置,这正是Tooltip控件为您完成的。其优点是您完全掌控工具提示的定位和外观,但是此方法要复杂得多。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接