简体   繁体   English

鼠标悬停时使工具提示保持打开状态

[英]Keep Tooltip Open when Mouse Hover

I created a ribbon in WPF using .NET 4.0 framework. 我使用.NET 4.0框架在WPF中创建了一个功能区。 I am trying to make use of ToolTipTitle , ToolTipDescription and ToolTipFooterDescription . 我正在尝试使用ToolTipTitleToolTipDescriptionToolTipFooterDescription 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">

A good example of this functionality is with Microsoft Excel. 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. 我正在尝试模仿该功能。

I've updated my answer, the below is a well tested solution to my problem and will mimic Microsoft Office's tooltip generation: 我已经更新了答案,以下是针对我的问题的经过良好测试的解决方案,它将模仿Microsoft Office的工具提示生成:

First, create the popup control: 首先,创建弹出控件:

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

Next, create the code behind for this control. 接下来,为该控件创建背后的代码。 For those of you who want the C# equivalent, you can head here . 对于那些想要C#等效语言的人,您可以在这里 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

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: 我将样式创建为资源字典(您可以将其称为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>

And finally, you must call your newly created ToolTip control in your Xaml markup like so: 最后,您必须像这样在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

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. 因此,这可能是实现此功能的复杂方法,但是一旦实现,这些工具提示将比默认工具提示好得多,尤其是在需要用户交互时。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM