Anche questo mi stava facendo impazzire stasera. Ho creato una ToolTipsottoclasse per gestire il problema. Per me, su .NET 4.0, la ToolTip.StaysOpenproprietà non "realmente" rimane aperta.
Nella classe seguente, usa la nuova proprietà ToolTipEx.IsReallyOpen, invece della proprietà ToolTip.IsOpen. Otterrai il controllo che desideri. Tramite la Debug.Print()chiamata, puoi guardare nella finestra di output del debugger quante volte this.IsOpen = falseviene chiamato! Così tanto per StaysOpen, o dovrei dire "StaysOpen"? Godere.
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);
}
}
}
Piccolo sproloquio: perché Microsoft non ha reso le DependencyPropertyproprietà (getter / setters) virtuali in modo da poter accettare / rifiutare / modificare le modifiche nelle sottoclassi? O crearne uno virtual OnXYZPropertyChangedper ognuno DependencyProperty? Ugh.
---Modificare---
La mia soluzione sopra sembra strana nell'editor XAML: il suggerimento è sempre visualizzato, bloccando del testo in Visual Studio!
Ecco un modo migliore per risolvere questo problema:
Alcuni 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>
Alcuni codici:
// 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);
}
}
Conclusione: c'è qualcosa di diverso nelle classi ToolTipe ContextMenu. Entrambi hanno classi "servizio", come ToolTipServicee ContextMenuService, che gestiscono determinate proprietà, ed entrambi utilizzano Popupcome controllo genitore "segreto" durante la visualizzazione. Infine, ho notato che TUTTI gli esempi di descrizioni comandi XAML sul Web non utilizzano la classe ToolTipdirettamente. Invece, incorporano un StackPanelcon TextBlocks. Cose che ti fanno dire: "hmmm ..."
ShowDurationproprietà, pensa che sia qualcosa di simile30,000. Qualunque cosa maggiore di quello e tornerà automaticamente a5000.