Cela me rendait aussi fou ce soir. J'ai créé une ToolTipsous - classe pour gérer le problème. Pour moi, sur .NET 4.0, la ToolTip.StaysOpenpropriété n'est pas "vraiment" reste ouverte.
Dans la classe ci-dessous, utilisez la nouvelle propriété ToolTipEx.IsReallyOpenau lieu de property ToolTip.IsOpen. Vous obtiendrez le contrôle que vous souhaitez. Via l' Debug.Print()appel, vous pouvez regarder dans la fenêtre de sortie du débogueur combien de fois this.IsOpen = falseest appelé! Tant pis StaysOpen, ou devrais-je dire "StaysOpen"? Prendre plaisir.
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);
}
}
}
Petite diatribe: Pourquoi Microsoft n'a-t-il pas rendu les DependencyPropertypropriétés (getters / setters) virtuelles afin que nous puissions accepter / rejeter / ajuster les changements dans les sous-classes? Ou en faire un virtual OnXYZPropertyChangedpour chacun DependencyProperty? Pouah.
---Éditer---
Ma solution ci-dessus semble étrange dans l'éditeur XAML - l'info-bulle est toujours affichée, bloquant du texte dans Visual Studio!
Voici une meilleure façon de résoudre ce problème:
Certains 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>
Un peu de code:
// 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);
}
}
Conclusion: Il y a quelque chose de différent dans les classes ToolTipet ContextMenu. Les deux ont des classes "service", comme ToolTipServiceet ContextMenuService, qui gèrent certaines propriétés, et les deux utilisent Popupcomme contrôle parent "secret" pendant l'affichage. Enfin, j'ai remarqué que TOUS les exemples XAML ToolTip sur le Web n'utilisent pas ToolTipdirectement la classe . Au lieu de cela, ils intègrent un StackPanelavec l' TextBlockart. Des choses qui vous font dire: "hmmm ..."
ShowDurationpropriété, pensez que c'est quelque chose comme30,000. Tout ce qui est supérieur à cela et il reviendra par défaut5000.