Esto también me estaba volviendo loco esta noche. Creé una ToolTipsubclase para manejar el problema. Para mí, en .NET 4.0, la ToolTip.StaysOpenpropiedad no "realmente" permanece abierta.
En la siguiente clase, use la nueva propiedad ToolTipEx.IsReallyOpen, en lugar de la propiedad ToolTip.IsOpen. Obtendrá el control que desea. A través de la Debug.Print()llamada, puede ver en la ventana de salida del depurador cuántas veces this.IsOpen = falsese llama. ¿Tanto para StaysOpen, o debería decir "StaysOpen"? Disfrutar.
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);
}
}
}
Pequeña perorata: ¿Por qué Microsoft no hizo que las DependencyPropertypropiedades (captadores / definidores) fueran virtuales para que podamos aceptar / rechazar / ajustar cambios en subclases? ¿O hacer una virtual OnXYZPropertyChangedpara todos y cada uno DependencyProperty? Ugh.
---Editar---
Mi solución anterior se ve extraña en el editor XAML: ¡la información sobre herramientas siempre se muestra, bloqueando parte del texto en Visual Studio!
Aquí hay una mejor manera de resolver este problema:
Algunos 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>
Algún código:
// 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);
}
}
Conclusión: hay algo diferente en las clases ToolTipy ContextMenu. Ambos tienen clases de "servicio", como ToolTipServicey ContextMenuService, que administran ciertas propiedades, y ambos se utilizan Popupcomo un control principal "secreto" durante la visualización. Finalmente, noté que TODOS los ejemplos de información sobre herramientas XAML en la Web no usan la clase ToolTipdirectamente. En su lugar, incrustan a StackPanelcon TextBlocks. Cosas que te hacen decir: "hmmm ..."
ShowDurationpropiedad, creo que es algo así30,000. Cualquier cosa mayor que eso y volverá por defecto a5000.