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

时间:2013-05-15 09:11:18

标签: c# .net wpf xaml tooltip

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

问题在于,有时工具提示并不总是放在正确的位置(即靠近窗口边缘),这意味着工具提示箭头不再指向正确的位置......是否还存在这个问题?或者我可以为每个位置展示位置创建特定样式吗?

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

2 个答案:

答案 0 :(得分:1)

也许您可以试试这个,我只需将Placement设置为Center并添加HorizontalOffset以匹配您在模板中创建的箭头。

然而,它不会在控件上垂直居中,因此您可以创建一个IValueConverter并计算控件的大小并除以2,或者您可以向StackPanel添加一个虚拟元素与Border相同的大小,应该使ToolTip居中,而不需要任何代码

<Style x:Key="{x:Type ToolTip}" TargetType="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="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>

答案 1 :(得分:0)

最简单的方法是使用控制树中存在的UIElement作为工具提示的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元素的原点。如果您有一个固定的路径大小,并且PlacementTarget始终位于相对于您要显示工具提示的控件的相同位置,那么这可以正常工作。

如果需要将工具提示相对于触发工具提示的控件定位,则必须每次打开工具提示时将路径数据设置为动态并计算在工具提示控件中创建新路径数据的距离。 对于这种情况,您必须处理Tooltip.IsOpened事件并实现此逻辑。如果你使用的是PlacementTarget,那么你总是知道相对于你的控件的方向,这样就可以更容易地计算出路径顶点。

另一种有效但方式更复杂的方法是实现自己的Popup,当你将鼠标移到控件上时会显示。您需要实现一些计算才能获得弹出窗口相对于Control的位置,这正是Tooltip控件为您所做的工作。这样做的好处是您可以完全控制工具提示的位置及其外观。