यह भी मुझे आज रात पागल कर रहा था। मैंने ToolTip
इस मुद्दे को संभालने के लिए एक उपवर्ग बनाया । मेरे लिए, .NET 4.0 पर, ToolTip.StaysOpen
संपत्ति "वास्तव में" खुली नहीं रहती है।
नीचे की कक्षा में, संपत्ति ToolTipEx.IsReallyOpen
के बजाय, नई संपत्ति का उपयोग करें ToolTip.IsOpen
। आपको मनचाहा नियंत्रण मिलेगा। Debug.Print()
कॉल के माध्यम से , आप डिबगर आउटपुट विंडो में देख सकते हैं कि कितनी बार this.IsOpen = false
कॉल किया जाता है! के लिए इतना StaysOpen
, या मुझे कहना चाहिए "StaysOpen"
? का आनंद लें।
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);
}
}
}
छोटा शेख़ी: माइक्रोसॉफ्ट ने DependencyProperty
गुण (गेटर्स / सेटर) को आभासी क्यों नहीं बनाया ताकि हम उपवर्गों में बदलावों को स्वीकार / अस्वीकार / समायोजित कर सकें? या हर एक के virtual OnXYZPropertyChanged
लिए एक बनाने के लिए DependencyProperty
? ओह।
--- संपादित करें ---
ऊपर का मेरा समाधान XAML संपादक में अजीब लग रहा है - टूलटिप हमेशा दिखा रहा है, विजुअल स्टूडियो में कुछ पाठ को अवरुद्ध कर रहा है!
यहाँ इस समस्या को हल करने का एक बेहतर तरीका है:
कुछ 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>
कुछ कोड:
// 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);
}
}
निष्कर्ष: कुछ कक्षाओं के बारे में अलग है ToolTip
और ContextMenu
। दोनों में "सेवा" वर्ग हैं, जैसे ToolTipService
और ContextMenuService
, जो कुछ गुणों का प्रबंधन करते हैं, और दोनों Popup
प्रदर्शन के दौरान "गुप्त" मूल नियंत्रण के रूप में उपयोग करते हैं। अंत में, मैंने देखा कि वेब पर सभी XAML टूलटिप उदाहरण ToolTip
सीधे वर्ग का उपयोग नहीं करते हैं। इसके बजाय, वे एस के StackPanel
साथ एम्बेड करते हैं TextBlock
। चीजें जो आपको कहती हैं: "हम्म्म ..."
ShowDuration
है, सोचें कि यह कुछ ऐसा है30,000
। इससे अधिक कुछ भी और यह डिफ़ॉल्ट रूप से वापस आ जाएगा5000
।