Das hat mich heute Abend auch verrückt gemacht. Ich habe eine ToolTip
Unterklasse erstellt, um das Problem zu beheben. Für mich unter .NET 4.0 ToolTip.StaysOpen
bleibt die Eigenschaft nicht "wirklich" offen.
Verwenden Sie in der folgenden Klasse die neue Eigenschaft ToolTipEx.IsReallyOpen
anstelle der Eigenschaft ToolTip.IsOpen
. Sie erhalten die Kontrolle, die Sie wollen. Über den Debug.Print()
Aufruf können Sie im Debugger-Ausgabefenster sehen, wie oft this.IsOpen = false
aufgerufen wird! Soviel zu StaysOpen
oder soll ich sagen "StaysOpen"
? Genießen.
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);
}
}
}
Kleiner Scherz: Warum hat Microsoft DependencyProperty
Eigenschaften (Getter / Setter) nicht virtuell gemacht, damit wir Änderungen in Unterklassen akzeptieren / ablehnen / anpassen können? Oder virtual OnXYZPropertyChanged
für jeden etwas machen DependencyProperty
? Pfui.
---Bearbeiten---
Meine obige Lösung sieht im XAML-Editor seltsam aus - der Tooltip wird immer angezeigt und blockiert Text in Visual Studio!
Hier ist ein besserer Weg, um dieses Problem zu lösen:
Einige 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>
Etwas 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);
}
}
Fazit: Etwas ist anders an Klassen ToolTip
und ContextMenu
. Beide haben "Service" -Klassen wie ToolTipService
und ContextMenuService
, die bestimmte Eigenschaften verwalten, und beide Popup
werden während der Anzeige als "geheimes" übergeordnetes Steuerelement verwendet. Schließlich habe ich festgestellt, dass ALLE XAML ToolTip-Beispiele im Web die Klasse nicht ToolTip
direkt verwenden. Stattdessen binden sie ein StackPanel
mit TextBlock
s ein. Dinge, die dich sagen lassen: "hmmm ..."
ShowDuration
Eigenschaft, denken Sie, es ist so etwas wie30,000
. Alles, was größer ist, wird standardmäßig wieder verwendet5000
.