鼠标悬停时保持工具提示打开 [英] Keep Tooltip Open when Mouse Hover

查看:28
本文介绍了鼠标悬停时保持工具提示打开的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I created a ribbon in WPF using .NET 4.0 framework. I am trying to make use of ToolTipTitle, ToolTipDescription and ToolTipFooterDescription. Since my tooltips will have hyperlinks, how can I make it so that when the mouse hovers over the tooltip, the tooltip stays open?

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

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

A good example of this functionality is with Microsoft Excel. When you hover over a ribbon button, an advanced tool tip will display to the user, and if the user hovers over the tooltip, it will remain open. I am trying to mimic that functionality.

推荐答案

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

I've updated my answer, the below is a well tested solution to my problem and will mimic Microsoft Office's tooltip generation:

首先,创建弹出控件:

<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# 等效项的人,您可以前往这里.这是我获得创建控件模板的参考.

Next, create the code behind for this control. For those of you who want the C# equivalent, you can head here. This is where I got the reference for creating a control template.

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,但您也可以将您的样式直接嵌入到 popup xaml 控件标记中:

The third step is to create the popup functionality, which is best done via styles. I created my style as a resource dictionary (you can call it PopupStyle.xaml, but you can also embed your style directly within the popup xaml control markup:

<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 控件:

And finally, you must call your newly created ToolTip control in your Xaml markup like so:

<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

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

So this may be a complicated way to achieve this functionality, however once implemented, these tooltips are much better than the default tooltips, especially if you require user interaction.

这篇关于鼠标悬停时保持工具提示打开的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆