Skip to content

Commit 088d184

Browse files
authored
Tooltip Direct Manipulation Fix (#7417)
* Tooltip Direct Manipulation Fix * Fix GetBetweenShowDelay NRE
1 parent c8af54f commit 088d184

File tree

1 file changed

+35
-4
lines changed

1 file changed

+35
-4
lines changed

src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/PopupControlService.cs

+35-4
Original file line numberDiff line numberDiff line change
@@ -468,10 +468,21 @@ private void ShowToolTip(DependencyObject o, bool fromKeyboard)
468468
}
469469

470470
_currentToolTip.SetValue(OwnerProperty, o);
471-
_currentToolTip.Opened += OnToolTipOpened;
472471
_currentToolTip.Closed += OnToolTipClosed;
473472
_currentToolTip.FromKeyboard = fromKeyboard;
474-
_currentToolTip.IsOpen = true;
473+
474+
if (!_currentToolTip.IsOpen)
475+
{
476+
// open the tooltip, and finish the initialization when its popup window is available.
477+
_currentToolTip.Opened += OnToolTipOpened;
478+
_currentToolTip.IsOpen = true;
479+
}
480+
else
481+
{
482+
// If the tooltip is already open, initialize it now. This only happens when the
483+
// app manages the tooltip directly.
484+
SetSafeArea(_currentToolTip);
485+
}
475486

476487
CurrentToolTipTimer = new DispatcherTimer(DispatcherPriority.Normal);
477488
CurrentToolTipTimer.Interval = TimeSpan.FromMilliseconds(ToolTipService.GetShowDuration(o));
@@ -632,6 +643,7 @@ private void ClearServiceProperties(ToolTip tooltip)
632643
{
633644
tooltip.ClearValue(OwnerProperty);
634645
tooltip.FromKeyboard = false;
646+
tooltip.Closed -= OnToolTipClosed;
635647

636648
if ((bool)tooltip.GetValue(ServiceOwnedProperty))
637649
{
@@ -727,8 +739,27 @@ private void OnToolTipOpened(object sender, EventArgs e)
727739
private void OnToolTipClosed(object sender, EventArgs e)
728740
{
729741
ToolTip toolTip = (ToolTip)sender;
730-
toolTip.Closed -= OnToolTipClosed;
731-
ClearServiceProperties(toolTip);
742+
if (toolTip != CurrentToolTip)
743+
{
744+
// if we manage the tooltip (the normal case), the current tooltip closes via
745+
// 1. DismissCurrentToolTip sets _currentToolTip=null and calls CloseToolTip
746+
// 2. CloseToolTip sets toolTip.IsOpen=false, and returns
747+
// 3. Asynchronously, the tooltip raises the Closed event (after popup animations have run)
748+
// 4. our event handler OnToolTipClosed gets here
749+
// It's now time to do the final cleanup, which includes removing this event handler.
750+
ClearServiceProperties(toolTip);
751+
}
752+
else
753+
{
754+
// we get here if the app closes the current tooltip or its popup directly.
755+
// Do nothing (i.e. ignore the event). This leaves the service properties in place -
756+
// eventually DismissCurrentToolTip will call CloseToolTip, which needs them
757+
// (in particular the Owner property). When that happens, either
758+
// a. tooltip.IsOpen==false. CloseToolTip clears the service properties immediately.
759+
// b. tooltip.IsOpen==true. (This can happen if the app re-opens the tooltip directly.)
760+
// CloseToolTip proceeds as in step 2 of the normal case.
761+
// Either way, the final cleanup happens.
762+
}
732763
}
733764

734765
// The previous tooltip hasn't closed and we are trying to open a new one

0 commit comments

Comments
 (0)