2009-05-22 96 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