2009-05-22 91 views
91

我有一个标签工具提示,我希望它保持打开状态,直到用户 将鼠标移动到不同的控件。强制WPF工具提示留在屏幕上

我曾尝试在提示以下属性:

StaysOpen="True" 

TooltipService.ShowDuration = "60000" 

但在这两种情况下,工具提示仅显示了整整5秒。

为什么这些值被忽略?

+0

对于`ShowDuration`属性,有一个强制*的某处*的最大值,认为它类似`30,000`。任何比这更大的东西,它会默认回到`5000`。 – Dennis 2011-09-29 10:43:38

+2

@丹尼斯:我测试了WPF 3.5和`ToolTipService.ShowDuration =“60000”`工作。它没有默认回到`5000`。 – 2011-12-02 15:28:57

+0

@emddudley:工具提示实际上是否保持开放60000ms?您可以将ToolTipService.ShowDuration属性设置为* any * value> = 0(即Int32.MaxValue),但工具提示不会保持打开状态。 – Dennis 2011-12-02 16:34:38

回答

75

把这段代码放在初始化部分。

ToolTipService.ShowDurationProperty.OverrideMetadata(
    typeof(DependencyObject), new FrameworkPropertyMetadata(Int32.MaxValue)); 
5

我前几天只是摔跤WPF Tooltip。似乎不可能阻止它自己出现并消失,所以最终我采取了处理事件的办法。例如,我想停止打开它,除非它有一些内容,所以我处理的Opened事件,然后这样做:

tooltip.IsOpen = (tooltip.Content != null); 

这是一个黑客,但它的工作。

假设您可以类似地处理Closed事件并告诉它再次打开,从而保持它可见。

8

您可能希望使用Popup而不是Tooltip,因为Tooltip假定您以预定义的UI标准方式使用它。

我不确定为什么StaysOpen不起作用,但ShowDuration的工作方式与MSDN中记录的一样 - 它是在显示工具提示时显示的时间量。将其设置为少量(例如500毫秒)以查看差异。

在你的情况下,诀窍是维持“最后一次控制”状态,但是一旦你有了这个应该是相当简单的动态更改展示位置目标和内容(手动或通过绑定)使用一个弹出窗口,或隐藏最后一个可见的弹出窗口,如果你使用多个。

对于Window调整大小和移动(Popups不会移动容器),Popups有一些小问题,所以您可能也想在调整行为时考虑到这一点。有关更多详细信息,请参阅this link

HTH。

0

此外,如果您想将任何其他控件放在您的工具提示中,它将不会被集中,因为工具提示本身可以获得焦点。就像micahtan说的那样,你最好的镜头是Popup。

145

TooltipService.ShowDuration工作,但你必须有工具提示,这样设置的对象:

<Label ToolTipService.ShowDuration="12000" Name="lblShowTooltip" Content="Shows tooltip"> 
    <Label.ToolTip> 
     <ToolTip> 
      <TextBlock>Hello world!</TextBlock> 
     </ToolTip> 
    </Label.ToolTip> 
</Label> 

我会说,之所以选择这种设计,因为它允许不同的不同的超时相同的提示控制。

-4
ToolTipService.ShowDurationProperty.OverrideMetadata(
    typeof(DependencyObject), new FrameworkPropertyMetadata(Int32.MaxValue)); 

这是为我工作。将此行复制到您的类构造函数中。

12

今晚这也让我疯狂。我创建了一个ToolTip子类来处理这个问题。对我而言,在.NET 4.0上,ToolTip.StaysOpen属性并非“真正”保持打开状态。

在下面的类中,使用新属性ToolTipEx.IsReallyOpen而不是属性ToolTip.IsOpen。你会得到你想要的控制。通过调用Debug.Print(),您可以在调试器输出窗口中看到调用this.IsOpen = false的次数!这么多的StaysOpen,或者我应该说"StaysOpen"?请享用。

public class ToolTipEx : ToolTip 
{ 
    static ToolTipEx() 
    { 
     IsReallyOpenProperty = 
      DependencyProperty.Register(
       "IsReallyOpen", 
       typeof(bool), 
       typeof(ToolTipEx), 
       new FrameworkPropertyMetadata(
        defaultValue: false, 
        flags: FrameworkPropertyMetadataOptions.None, 
        propertyChangedCallback: StaticOnIsReallyOpenedChanged)); 
    } 

    public static readonly DependencyProperty IsReallyOpenProperty; 

    protected static void StaticOnIsReallyOpenedChanged(
     DependencyObject o, DependencyPropertyChangedEventArgs e) 
    { 
     ToolTipEx self = (ToolTipEx)o; 
     self.OnIsReallyOpenedChanged((bool)e.OldValue, (bool)e.NewValue); 
    } 

    protected void OnIsReallyOpenedChanged(bool oldValue, bool newValue) 
    { 
     this.IsOpen = newValue; 
    } 

    public bool IsReallyOpen 
    { 
     get 
     { 
      bool b = (bool)this.GetValue(IsReallyOpenProperty); 
      return b; 
     } 
     set { this.SetValue(IsReallyOpenProperty, value); } 
    } 

    protected override void OnClosed(RoutedEventArgs e) 
    { 
     System.Diagnostics.Debug.Print(String.Format(
      "OnClosed: IsReallyOpen: {0}, StaysOpen: {1}", this.IsReallyOpen, this.StaysOpen)); 
     if (this.IsReallyOpen && this.StaysOpen) 
     { 
      e.Handled = true; 
      // We cannot set this.IsOpen directly here. Instead, send an event asynchronously. 
      // DispatcherPriority.Send is the highest priority possible. 
      Dispatcher.CurrentDispatcher.BeginInvoke(
       (Action)(() => this.IsOpen = true), 
       DispatcherPriority.Send); 
     } 
     else 
     { 
      base.OnClosed(e); 
     } 
    } 
} 

小咆哮:为什么没有微软做DependencyProperty属性(getter/setter方法)虚拟的,这样我们就可以接受/拒绝/调整在子类中的变化?或者为每个DependencyProperty制作virtual OnXYZPropertyChanged?啊。

---编辑---

上面我的解决方案看起来在XAML编辑怪异 - 工具提示总是显示,堵在Visual Studio中一些文字!

这里是解决这个问题的一个更好的方法:

一些XAML:

<!-- Need to add this at top of your XAML file: 
    xmlns:System="clr-namespace:System;assembly=mscorlib" 
--> 
<ToolTip StaysOpen="True" Placement="Bottom" HorizontalOffset="10" 
     ToolTipService.InitialShowDelay="0" ToolTipService.BetweenShowDelay="0" 
     ToolTipService.ShowDuration="{x:Static Member=System:Int32.MaxValue}" 
>This is my tooltip text.</ToolTip> 

一些代码:

// Alternatively, you can attach an event listener to FrameworkElement.Loaded 
public override void OnApplyTemplate() 
{ 
    base.OnApplyTemplate(); 

    // Be gentle here: If someone creates a (future) subclass or changes your control template, 
    // you might not have tooltip anymore. 
    ToolTip toolTip = this.ToolTip as ToolTip; 
    if (null != toolTip) 
    { 
     // If I don't set this explicitly, placement is strange. 
     toolTip.PlacementTarget = this; 
     toolTip.Closed += new RoutedEventHandler(OnToolTipClosed); 
    } 
} 

protected void OnToolTipClosed(object sender, RoutedEventArgs e) 
{ 
    // You may want to add additional focus-related tests here. 
    if (this.IsKeyboardFocusWithin) 
    { 
     // We cannot set this.IsOpen directly here. Instead, send an event asynchronously. 
     // DispatcherPriority.Send is the highest priority possible. 
     Dispatcher.CurrentDispatcher.BeginInvoke(
      (Action)delegate 
       { 
        // Again: Be gentle when using this.ToolTip. 
        ToolTip toolTip = this.ToolTip as ToolTip; 
        if (null != toolTip) 
        { 
         toolTip.IsOpen = true; 
        } 
       }, 
      DispatcherPriority.Send); 
    } 
} 

结论:一些是关于类ToolTipContextMenu不同。两者都有“服务”类,如ToolTipServiceContextMenuService,它们管理某些属性,并且在显示期间都使用Popup作为“秘密”父控件。最后,我注意到ALL Web上的XAML ToolTip示例不直接使用类ToolTip。相反,他们嵌入与TextBlock s。事情让你说:“嗯......”只是为了完整起见

2

: 在代码中,它看起来是这样的:

ToolTipService.SetShowDuration(element, 60000); 
5

如果要指定在Window只有某些元素有 有效不确定ToolTip持续时间,您可以在您的Window.Resources中为这些元素定义Style。这里是一个StyleButton有这样一个ToolTip

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:sys="clr-namespace:System;assembly=mscorlib" 
    ...> 
    ... 
    <Window.Resources> 
     <Style x:Key="ButtonToolTipIndefinate" TargetType="{x:Type Button}"> 
      <Setter Property="ToolTipService.ShowDuration" 
        Value="{x:Static Member=sys:Int32.MaxValue}"/> 
     </Style> 
     ... 
    </Window.Resources> 
    ... 
    <Button Style="{DynamicResource ButtonToolTipIndefinate}" 
      ToolTip="This should stay open"/> 
    <Button ToolTip="This Should disappear after the default time."> 
    ... 

你也可以添加Style.ResourcesStyle改变ToolTip它显示的外观,例如:

<Style x:Key="ButtonToolTipTransparentIndefinate" TargetType="{x:Type Button}"> 
    <Style.Resources> 
     <Style x:Key="{x:Type ToolTip}" TargetType="{x:Type ToolTip}"> 
      <Setter Property="Background" Value="Transparent"/> 
      <Setter Property="BorderBrush" Value="Transparent"/> 
      <Setter Property="HasDropShadow" Value="False"/> 
     </Style> 
    </Style.Resources> 
    <Setter Property="ToolTipService.ShowDuration" 
      Value="{x:Static Member=sys:Int32.MaxValue}"/> 
</Style> 

注意:我这样做了,我也在Style中使用了BasedOn,因此我的自定义控件版本中定义的其他所有内容都将应用于正常的ToolTip