首页 > 解决方案 > 鼠标悬停时保持工具提示打开

问题描述

我使用 .NET 4.0 框架在 WPF 中创建了一个功能区。我正在尝试使用ToolTipTitleToolTipDescriptionToolTipFooterDescription。由于我的工具提示会有超链接,我怎样才能使鼠标悬停在工具提示上时,工具提示保持打开状态?

<rib:RibbonMenuButton ToolTipTitle="Title" ToolTipDescription="My Description" ToolTipFooterDescription="My Footer With a Link">

此功能的一个很好的例子是 Microsoft Excel。当您将鼠标悬停在功能区按钮上时,将向用户显示高级工具提示,如果用户将鼠标悬停在工具提示上,它将保持打开状态。我正在尝试模仿该功能。

标签: c#wpfvb.netxamltooltip

解决方案


我已经更新了我的答案,以下是针对我的问题的经过良好测试的解决方案,并将模仿 Microsoft Office 的工具提示生成:

首先,创建弹出控件:

<Popup x:Class="WPF.Tooltip" AllowsTransparency="True"
       x:Name="TT_Popup_Control"
       xmlns:WPF="clr-namespace:Project_Namespace.WPF"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Project_Namespace"
             mc:Ignorable="d" 
             d:DesignHeight="100" d:DesignWidth="300">
    <Grid>
        <Grid.Resources>
            <Style TargetType="TextBlock">
                <Setter Property="Margin" Value="5" />
                <Setter Property="FontFamily" Value="Sans Serif" />
                <Setter Property="FontSize" Value="11" />
                <Setter Property="TextWrapping" Value="Wrap" />
            </Style>
            <Style TargetType="{x:Type TextBlock}" x:Key="WrappingStyle">
                <Setter Property="TextWrapping" Value="Wrap"/>
            </Style>
        </Grid.Resources>
        <Border BorderBrush="LightGray" BorderThickness="1,1,0,0">
            <Border 
                    BorderThickness="0,0,15,15" 
                    BorderBrush="Transparent"                
                    CornerRadius="0" 
                    Margin="0"
                 >
                <Border.Effect>
                    <DropShadowEffect BlurRadius="10" Opacity="0.8"  ShadowDepth="5" Direction="-40" RenderingBias="Quality" />
                </Border.Effect>
                <StackPanel Background="#efefef">
                    <Grid Margin="5,0,5,0">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*" />
                            <RowDefinition Height="*" />
                            <RowDefinition Height="*" />
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="1*" />
                            <ColumnDefinition Width="3*" />
                        </Grid.ColumnDefinitions>

                        <!-- Title -->
                        <TextBlock Grid.ColumnSpan="2" Grid.Row="0" FontWeight="Bold" Text="{Binding Title, ElementName=TT_Popup_Control}" />

                        <!-- Description -->
                        <TextBlock Grid.Column="0" Grid.Row="1">
                            <ContentPresenter Content="{Binding Image, ElementName=TT_Popup_Control}" />
                        </TextBlock>
                        <TextBlock Grid.Column="1" Grid.Row="1">
                            <ContentPresenter Content="{Binding Desc, ElementName=TT_Popup_Control}">
                                <ContentPresenter.Resources>
                                    <Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource WrappingStyle}"/>
                                </ContentPresenter.Resources>
                            </ContentPresenter>
                        </TextBlock>
                        <Separator Grid.ColumnSpan="2" Grid.Row="2"  />

                        <!-- Image -->
                        <TextBlock Grid.ColumnSpan="2" Grid.Row="3">
                            <Image Margin="0,0,10,0" Width="16" Source="pack://application:,,,/Path/To/Image/help_icon.png" />
                            <TextBlock Margin="0,-5,0,0">
                                <Hyperlink RequestNavigate="Hyperlink_RequestNavigate" NavigateUri="{Binding Footer, ElementName=TT_Popup_Control}">Tell Me More</Hyperlink>
                            </TextBlock>
                        </TextBlock>
                    </Grid>
                </StackPanel>
            </Border>
        </Border>
    </Grid>
</Popup>

接下来,为此控件创建代码。对于那些想要 C# 等价物的人,您可以前往此处。这是我获得创建控件模板的参考的地方。

Imports System.Windows
Namespace WPF
    Public Class Tooltip
        Public Shared ReadOnly TitleProperty As DependencyProperty = DependencyProperty.Register("Title", GetType(Object), GetType(WPF.Tooltip), New PropertyMetadata(vbNull))
        Public Shared ReadOnly DescProperty As DependencyProperty = DependencyProperty.Register("Desc", GetType(Object), GetType(WPF.Tooltip), New PropertyMetadata(vbNull))
        Public Shared ReadOnly FooterProperty As DependencyProperty = DependencyProperty.Register("Footer", GetType(Object), GetType(WPF.Tooltip), New PropertyMetadata(vbNull))
        Public Shared ReadOnly ImageProperty As DependencyProperty = DependencyProperty.Register("Image", GetType(Object), GetType(WPF.Tooltip), New PropertyMetadata(vbNull))

        Public Property Title As Object
            Get
                Return GetValue(TitleProperty)
            End Get
            Set(value As Object)
                SetValue(TitleProperty, value)
            End Set
        End Property
        Public Property Desc As Object
            Get
                Return GetValue(DescProperty)
            End Get
            Set(value As Object)
                SetValue(DescProperty, value)
            End Set
        End Property
        Public Property Footer As Object
            Get
                Return GetValue(FooterProperty)
            End Get
            Set(value As Object)
                SetValue(FooterProperty, value)
            End Set
        End Property
        Public Property Image As Object
            Get
                Return GetValue(ImageProperty)
            End Get
            Set(value As Object)
                SetValue(ImageProperty, value)
            End Set
        End Property

        Private Sub Hyperlink_RequestNavigate(sender As Object, e As Navigation.RequestNavigateEventArgs)
            System.Diagnostics.Process.Start(e.Uri.ToString())
        End Sub
    End Class
End Namespace

第三步是创建弹出功能,最好通过样式来完成。我将样式创建为资源字典(您可以将其命名为 PopupStyle.xaml,但您也可以将样式直接嵌入到弹出 xaml 控件标记中:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Classic" 
    xmlns:System="clr-namespace:System;assembly=mscorlib">

<Style x:Key="TT_Popup" TargetType="Popup">
        <Setter Property="VerticalOffset" Value="20" />
        <Setter Property="MaxWidth" Value="500" />
        <Setter Property="MinWidth" Value="50" />
        <Style.Triggers>
            <DataTrigger Binding="{Binding PlacementTarget.IsMouseOver, RelativeSource={RelativeSource Self}}" Value="True">
                <DataTrigger.EnterActions>
                    <BeginStoryboard x:Name="OpenPopupStoryBoard" >
                        <Storyboard>
                            <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen" FillBehavior="HoldEnd">
                                <DiscreteBooleanKeyFrame KeyTime="0:0:1.00" Value="True"/>
                            </BooleanAnimationUsingKeyFrames>
                        </Storyboard>
                    </BeginStoryboard>
                </DataTrigger.EnterActions>
                <DataTrigger.ExitActions>
                    <PauseStoryboard BeginStoryboardName="OpenPopupStoryBoard"/>
                    <BeginStoryboard x:Name="ClosePopupStoryBoard">
                        <Storyboard>
                            <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen" FillBehavior="HoldEnd">
                                <DiscreteBooleanKeyFrame KeyTime="0:0:0.35" Value="False"/>
                            </BooleanAnimationUsingKeyFrames>
                        </Storyboard>
                    </BeginStoryboard>
                </DataTrigger.ExitActions>
            </DataTrigger>
            <DataTrigger Binding="{Binding PlacementTarget.IsMouseCaptured, RelativeSource={RelativeSource Self}}" Value="True">
                <DataTrigger.EnterActions>
                    <PauseStoryboard BeginStoryboardName="OpenPopupStoryBoard"/>
                    <BeginStoryboard x:Name="CloseImmediatelyPopupStoryBoard" >
                        <Storyboard>
                            <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen" FillBehavior="HoldEnd">
                                <DiscreteBooleanKeyFrame KeyTime="0:0:0.0" Value="False"/>
                            </BooleanAnimationUsingKeyFrames>
                        </Storyboard>
                    </BeginStoryboard>
                </DataTrigger.EnterActions>
            </DataTrigger>
            <DataTrigger Binding="{Binding PlacementTarget.IsMouseOver, RelativeSource={RelativeSource Self}}" Value="False">
                <DataTrigger.ExitActions>
                    <RemoveStoryboard BeginStoryboardName="CloseImmediatelyPopupStoryBoard" />
                </DataTrigger.ExitActions>
            </DataTrigger>

            <Trigger Property="IsMouseOver" Value="True">
                <Trigger.EnterActions>
                    <PauseStoryboard BeginStoryboardName="ClosePopupStoryBoard" />
                </Trigger.EnterActions>
                <Trigger.ExitActions>
                    <PauseStoryboard BeginStoryboardName="OpenPopupStoryBoard"/>
                    <ResumeStoryboard BeginStoryboardName="ClosePopupStoryBoard" />
                </Trigger.ExitActions>
            </Trigger>
        </Style.Triggers>
    </Style>
</ResourceDictionary>

最后,您必须在 Xaml 标记中调用新创建的 ToolTip 控件,如下所示:

<UserControl xmlns:WPF="clr-namespace:Project_Namespace.WPF"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             >
     <UserControl.Resources>
          <ResourceDictionary.MergedDictionaries>
               <ResourceDictionary Source="PopupStyle.xaml"/>
                    </ResourceDictionary.MergedDictionaries>
               </ResourceDictionary>
     </UserControl.Resources>
     <Grid>
          <Button x:Name="button_name" />

           <!-- Tooltips -->
          <WPF:Tooltip Style="{StaticResource TT_Popup}" PlacementTarget="{Binding ElementName=button_name}">
               <WPF:Tooltip.Title>
                    Tooltip Title
               </WPF:Tooltip.Title>
               <WPF:Tooltip.Image>
                    <Image Source="pack://application:,,,/Path/To/Image.png" />
               </WPF:Tooltip.Image>
               <WPF:Tooltip.Desc>
                    Your Description here
               </WPF:Tooltip.Desc>
               <WPF:Tooltip.Footer>
                    www.example.com
               </WPF:Tooltip.Footer>
          </WPF:Tooltip>
     </Grid>
</UserControl

因此,这可能是实现此功能的一种复杂方法,但是一旦实施,这些工具提示比默认工具提示要好得多,尤其是在您需要用户交互的情况下。


推荐阅读