Ini juga membuatku gila malam ini. Saya membuat ToolTip
subclass untuk menangani masalah tersebut. Bagi saya, di .NET 4.0,ToolTip.StaysOpen
properti tidak "benar-benar" tetap buka.
Di kelas di bawah ini, gunakan properti baru ToolTipEx.IsReallyOpen
, bukan properti ToolTip.IsOpen
. Anda akan mendapatkan kendali yang Anda inginkan. Melalui Debug.Print()
panggilan, Anda dapat melihat di jendela Output debugger berapa kali this.IsOpen = false
dipanggil! Begitu banyak StaysOpen
, atau haruskah saya katakan "StaysOpen"
? Nikmati.
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);
}
}
}
Kata-kata kasar kecil: Mengapa Microsoft tidak membuat DependencyProperty
properti (getter / setter) virtual sehingga kami dapat menerima / menolak / menyesuaikan perubahan dalam subclass? Atau buat virtual OnXYZPropertyChanged
untuk setiap DependencyProperty
? Ugh.
--- Edit ---
Solusi saya di atas terlihat aneh di editor XAML - tooltip selalu ditampilkan, memblokir beberapa teks di Visual Studio!
Berikut cara yang lebih baik untuk mengatasi masalah ini:
Beberapa 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>
Beberapa kode:
// 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);
}
}
Kesimpulan: Ada sesuatu yang berbeda tentang kelas ToolTip
dan ContextMenu
. Keduanya memiliki kelas "layanan", seperti ToolTipService
dan ContextMenuService
, yang mengelola properti tertentu, dan keduanya digunakan Popup
sebagai kontrol induk "rahasia" selama tampilan. Akhirnya, saya perhatikan SEMUA contoh XAML ToolTip di Web tidak menggunakan class ToolTip
secara langsung. Sebaliknya, mereka menyematkan a StackPanel
dengan TextBlock
s. Hal yang membuatmu berkata: "hmmm ..."
ShowDuration
properti, anggaplah itu seperti itu30,000
. Apa pun yang lebih besar dari itu dan akan default kembali ke5000
.