Bu da bu gece beni deli ediyordu. ToolTipSorunu çözmek için bir alt sınıf oluşturdum . Benim için .NET 4.0'da, ToolTip.StaysOpenözellik "gerçekten" değil, açık kalıyor.
Aşağıdaki sınıfta yeni mülkü kullanın ToolTipEx.IsReallyOpen yerine kullanın ToolTip.IsOpen. İstediğiniz kontrolü alacaksınız. Via Debug.Print()çağrı, birçok kez sadece nasıl ayıklayıcı Çıktı penceresinde izleyebilirsiniz this.IsOpen = falsedenir! Çok mu StaysOpen, yoksa söylemeliyim "StaysOpen"? Zevk almak.
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);
}
}
}
Küçük rant: Microsoft neden DependencyPropertyözellikleri (alıcılar / ayarlayıcılar) sanal yapmadı, böylece alt sınıflardaki değişiklikleri kabul edebilir / reddedebilir / ayarlayabiliriz? Veya virtual OnXYZPropertyChangedher biri için bir tane DependencyPropertymi hazırlıyorsunuz ? Ugh.
---Düzenle---
Yukarıdaki çözümüm XAML düzenleyicide garip görünüyor - araç ipucu her zaman gösteriliyor, Visual Studio'daki bazı metinleri engelliyor!
İşte bu sorunu çözmenin daha iyi bir yolu:
Bazı 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>
Bazı kodlar:
// 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);
}
}
Sonuç: Sınıflar hakkında farklı bir şey var ToolTipve ContextMenu. Her ikisinin de belirli özellikleri yöneten ToolTipServiceve gibi "hizmet" sınıfları vardır ContextMenuServiceve her ikisi de Popupgörüntüleme sırasında "gizli" üst denetim olarak kullanılır. Son olarak, Web'deki TÜM XAML ToolTip örneklerinin ToolTipdoğrudan sınıfı kullanmadığını fark ettim . Bunun yerine, a StackPanelile TextBlocks yerleştirirler . Size şunu söyleten şeyler: "hmmm ..."
ShowDurationmülkiyet, bu gibi bir şey olduğunu düşünüyorum30,000. Bundan daha büyük herhangi bir şey ve varsayılan olarak geri dönecektir5000.