Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception opening right click menu if tooltip is shown #5730

Closed
rjsams opened this issue Nov 24, 2021 · 24 comments · Fixed by #5932
Closed

Exception opening right click menu if tooltip is shown #5730

rjsams opened this issue Nov 24, 2021 · 24 comments · Fixed by #5932
Assignees

Comments

@rjsams
Copy link

rjsams commented Nov 24, 2021

Version: 6.0.100
Commit: 9e8b04bbff
OS Build 22000.318

  • Does the bug reproduce also in WPF for .NET Framework 4.8?: Yes/No
    No, this did not reproduce with previous .NET versions

  • Is this bug related specifically to tooling in Visual Studio (e.g. XAML Designer, Code editing, etc...)? If yes, please file the issue via the instructions here.
    Does not appear to be tooling related.

Problem description:
Our application has started throwing exception after the update to .NET 6 with VS 2022.
The issue occurs when the application is attempting to open a right click menu while a tooltip is active. The repro case is not reliable and may be timing sensitive.

System.ArgumentNullException
HResult=0x80004003
Message=Value cannot be null. (Parameter 'element')
Source=PresentationFramework
StackTrace:
at System.Windows.Controls.ToolTipService.GetBetweenShowDelay(DependencyObject element)
at System.Windows.Controls.PopupControlService.CloseToolTip(ToolTip tooltip)
at System.Windows.Controls.PopupControlService.OnPostProcessInput(Object sender, ProcessInputEventArgs e)
at System.Windows.Input.InputManager.RaiseProcessInputEventHandlers(Tuple`2 postProcessInput, ProcessInputEventArgs processInputEventArgs)
at System.Windows.Input.InputManager.ProcessStagingArea()
at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.Run()
at System.Windows.Application.RunDispatcher(Object ignore)
at System.Windows.Application.RunInternal(Window window)
at System.Windows.Application.Run()
at ArpsEditor.App.Main()

Expected behavior:
No exception, same as behavior in .NET 5.

Minimal repro:

@CyberSinh
Copy link

I also encounter this exception in my application (Metatogger) since the upgrade to .NET 6.

@singhashish-wpf
Copy link
Member

Can we have a sample repro project to check it further?

@taquion87
Copy link

taquion87 commented Dec 2, 2021

I also encountered this exception since I upgraded to .NET 6. FWIW it is very hard to repro in the application while it is running, but it happens every time I am running my UI Tests with FlaUI.

Whenever I run my tests I get at some point the following crash:

image

@sa13m
Copy link

sa13m commented Dec 14, 2021

The same problem after the transition from .NET 5 to .NET 6.

Problem description:
Popup IsOpen binding exception Value cannot be null. (Parameter 'element').
There is no dependence, the exception occurs randomly, after opening the popup 10 times or 100. After the exception, pop-up windows (Popup, ToolTip, Window) do not work correctly, do not open or content inside cannot be selected with the mouse

@dragnilar
Copy link

We are having this problem also, and as others have said, it started after moving from .NET 5 to .NET 6. Whenever it happens (which as @sa13m stated, is seemingly random for users), we get these two exceptions sent to App Center:

Value cannot be null. (Parameter 'element') System.ArgumentNullException: Value cannot be null. (Parameter 'element')
   at System.Windows.Controls.ToolTipService.GetBetweenShowDelay(DependencyObject element)
   at System.Windows.Controls.PopupControlService.CloseToolTip(ToolTip tooltip)
   at System.Windows.Controls.PopupControlService.PromotePendingToolTipToCurrent(TriggerAction triggerAction)
   at System.Windows.Controls.PopupControlService.<>c__DisplayClass9_0.<BeginShowToolTip>b__0(Object s, EventArgs e)
   at System.Windows.Threading.DispatcherTimer.FireTick()
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)

Value cannot be null. (Parameter 'element') System.ArgumentNullException: Value cannot be null. (Parameter 'element')

   at System.Windows.Controls.ToolTipService.GetBetweenShowDelay(DependencyObject element)

   at System.Windows.Controls.PopupControlService.CloseToolTip(ToolTip tooltip)

   at System.Windows.Controls.PopupControlService.OnMouseMove(IInputElement directlyOver, RawMouseInputReport mouseReport)

   at System.Windows.Controls.PopupControlService.OnPostProcessInput(Object sender, ProcessInputEventArgs e)

   at System.Windows.Input.InputManager.RaiseProcessInputEventHandlers(Tuple`2 postProcessInput, ProcessInputEventArgs processInputEventArgs)

   at System.Windows.Input.InputManager.ProcessStagingArea()

   at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)

   at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)

   at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)

   at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)

   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)

   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)

   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)

   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)

@SamBent SamBent self-assigned this Jan 5, 2022
@SamBent
Copy link
Contributor

SamBent commented Jan 5, 2022

I understand that the race condition makes it hard to provide a repro. But can anyone supply a minimal app in which the problem arises (even if you can't cause the crash reliably)? Or describe how your real app sets up the tooltip and context menu? Or provide a time-travel trace of the crash?

In particular, I'd like to know

  • Is the tooltip declared explicitly (<Button.ToolTip> <ToolTip> ... </ToolTip></Button.ToolTip>), or implicitly (<Button ToolTip="my content").
  • Same for the context menu
  • What values do you declare for properties related to tooltip or context menu? (Either declared on the tooltip/menu, or declared as attached properties on the owner)
  • Do the tooltip and context menu belong to the same element?
  • Does your app handle any of the tooltip or context menu events: ToolTipOpening, ToolTipClosing, ContextMenuOpening, ContextMenuClosing, etc.
  • Does your app do anything explicit that affects the opening and closing of ToolTip or ContextMenu? (As opposed to simply declaring the tooltip/menu and letting WPF's default behavior do the work.)
  • What does your test harness do to cause the problem? Is it simulating mouse motion/clicks, or using UIAutomation, or calling WPF APIs, or something else? How does it decide when to initiate the next action? What specific actions lead to the crash?

@GSonofNun
Copy link

@SamBent it is very rare for me, but I somehow got lucky enough to trigger it while debugging, and now I'm at a point where the debugger is paused with this exception. What can I do to get you as much information as possible?

@SamBent
Copy link
Contributor

SamBent commented Jan 5, 2022

@GSonofNun Save a crash dump (with heap memory), and send it to me (sambent @ microsoft.com), or share a link. And answer my questions as best as possible. It will help to know if this can happen in the simplest case - implicit declarations, no special events or actions - or whether it needs the app to do something.

Thanks!

@sa13m
Copy link

sa13m commented Jan 5, 2022

@SamBent Minimal app Net6PopupProblem

public bool PaymentIsOpen
{
	get => _paymentIsOpen;
	set
	{
		try
		{
			SetProperty(ref _paymentIsOpen, value);
		}
		catch (Exception ex)
		{
			// !!! this exception
			MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
			_paymentIsOpen = false;
		}
	}
}

But opened popup(F5 key) more than 100 times there was no error. In the real app, the error happens 1-3 times during the day, after the exception, pop-up windows (Popup, ToolTip, Window) do not work correctly, do not open or content inside cannot be selected with the mouse, must restart the app

@SamBent
Copy link
Contributor

SamBent commented Jan 5, 2022

@sa13m - please fix the link to your minimal app. (It points to 'url')

@sa13m
Copy link

sa13m commented Jan 5, 2022

@SamBent sorry, fixed

@RWeigelt
Copy link

RWeigelt commented Jan 5, 2022

@SamBent I also have the problem of rare crashes. I use very similar tooltips in two locations of my application. One crashes after migrating from .NET5 to .NET6, the other does not. The crashing tooltip worked reliably in the .NET5 version and in the older .NET 4.x version of the application (never any problems under heavy usage).

I did not have the time yet to create a repro scenario, but here is a quick brain dump of everything that may be helpful:

  • The tooltip without any crashes is done in pure XAML, i.e. <Grid.Tooltop><ToolTip>...</ToolTip><Grid.Tooltop>
  • The tooltip that crashes is opened/closed in code (.IsOpen=true)
    • The tooltip is used for a control that uses custom layout for performance.
    • The tooltip is set in the control template via <Setter Property="ToolTip"><Setter.Value><ToolTip DataContext="{Binding Path=PlacementTarget, RelativeSource={x:Static RelativeSource.Self}}" Placement="Custom">...
    • In the PreviewMouseMove handler, a DispatcherTimer is (re)started for implementing a 750ms delay for the tooltip.
    • The event handler for the Tick event of the timer opens the tooltip (after closing an already opened tooltip if necessary)
    • The location of the tooltip is set via ToolTip.CustomPopupPlacementCallback.

@SamBent
Copy link
Contributor

SamBent commented Jan 6, 2022

@sa13m - your app doesn't have any tooltips or context menus. How is it relevant to this issue?
Also, your app doesn't display anything. Just an empty white window. It builds and loads without complaint, but does nothing as far as I can tell.

@RWeigelt - Is your rare crash really the one under discussion here - an ArgumentNullException at

at System.Windows.Controls.ToolTipService.GetBetweenShowDelay(DependencyObject element)
at System.Windows.Controls.PopupControlService.CloseToolTip(ToolTip tooltip)

while trying to open a context menu? From your brain dump, it's clear that you are definitely overriding/replacing the built-in tooltip behavior, and I suspect you are hitting a different problem than the one in this issue - some way in which the new 6.0 tooltip code isn't prepared for your custom logic. If so, you should open a separate issue and attach a repro.

@everyone I've been staring at the logic for opening and closing tooltips and context menus all day, without seeing how it could reach this ArgumentNullException. There's some re-entrancy or race condition that I haven't seen yet, so I need your help to see it. (I can easily "fix" this by testing for null, but I worry that something else will break later on. Need to understand how that null got to be there at all.)

@sa13m
Copy link

sa13m commented Jan 6, 2022

@SamBent press F5 to open popup, exception occurs when popup is opening

@RWeigelt
Copy link

RWeigelt commented Jan 6, 2022

@SamBent

@RWeigelt - Is your rare crash really the one under discussion here - an ArgumentNullException at

at System.Windows.Controls.ToolTipService.GetBetweenShowDelay(DependencyObject element)
at System.Windows.Controls.PopupControlService.CloseToolTip(ToolTip tooltip)

My crash is an ArgumentNullException with this stack trace (that's how I came across this GitHub issue via a web search).

while trying to open a context menu?

As far as I can remember, no.

I will try to come up with a repro and file a separate issue.

@SamBent
Copy link
Contributor

SamBent commented Jan 7, 2022

@sa13m

press F5 to open popup, exception occurs when popup is opening

But it can't be this exception (null argument when closing a tooltip), since there are no tooltips in your app. You should open a new issue about the exception you are seeing.

@RWeigelt If you're seeing the same stack trace, it's probably the same bug, or a minor variation. If you can repro it, please share it here.

@GSonofNun is seeing this stack trace without any involvement from context menu. He sent me a sample app based on his real app, but unfortunately it doesn't repro the crash. (He did find another bug: removing an element while its tooltip is open doesn't close the tooltip. I can fix that easily, but it doesn't explain the current issue.)

@rjsams
Copy link
Author

rjsams commented Jan 7, 2022

@SamBent In my case we are seeing this in a C# only, no XAML use case.

We create a new ToolTip as part of creating a UserControl
We then set ToolTip = to that new object

From OnMouseMove(..) we update the tooltip as needed depending on what the mouse is over
This is done by setting:
tooltip.Content = a string we dynamically create
tooltip.IsOpen = dynamic enable/disable depending on what the mouse is over.

Should it matter we update Content before IsOpen when setting IsOpen to true, when setting it to false we do not update Content.

@randalvs
Copy link

randalvs commented Jan 7, 2022

@SamBent, I also encounter this/an issue although the stack trace is not completely the same.
I uploaded a sample repo here
In my case it happens when I apply an implicit custom style for the popup (using a resource dictionary). When I remove the reference to the style (from app.xaml) the issue is gone.

repro-screen-recording

I'm not sure if this is the correct way to change the styling of the popup and if this is the same issue as mentioned above but at least it works in <=.net 5. I hope this helps you to investigate this further.

@SamBent
Copy link
Contributor

SamBent commented Jan 10, 2022

Thank you, @randalvs. Your repro illustrates what I was missing - how a ToolTip can have both IsOpen=true and Owner=null. It's because your app manipulates the tooltip's Popup directly (via the storyboards in your custom style). It sets Popup.IsOpen=false, which causes the tooltip to clear its (private) Owner property but doesn't change ToolTip.IsOpen. The crash occurs when the tooltip itself is closed.

I suspect all the complaints here boil down to the same thing: closing the tooltip's Popup directly (as opposed to closing the ToolTip object, and letting the PopupControlService close the Popup in response). It's not easy to do, as the Popup (and often the ToolTip itself) are private, but your repro shows one way to do it. I still don't see how it happens in the original case involving ContextMenu, but the fixes I'm contemplating will protect against any direct Popup manipulation, no matter how they're caused.

I'm not sure if this is the correct way to change the styling of the popup

A custom implicit style is fine for changing the visual appearance (colors, fonts, layout) of the Popup, but it's not so good for changing its behavior. I see some problems, some of which are present already in .NET 4.8, 3.1, and 5.0, and some made worse by the new ToolTip behavior in .NET 6.0. The style defines a very specific behavior, akin to the old default tooltip behavior from, say, .NET 4.5. Some consequences:

  • It applies the "tooltip-ish" behavior to all Popups, even those that don't belong to a ToolTip.
  • It ignores the tooltip properties InitialShowDelay, ShowDuration, etc. and interacts with those properties in potentially confusing ways. For example, WPF starts the BetweenShowDelay timer when the ToolTip closes, which with your behavior can be much later than when the Popup closes, leading to unexpected delays (or lack of delays) when mousing between controls that have tooltips.
  • It doesn't support new tooltip behavior, and can actually interfere. For example, it breaks keyboard navigation behavior: tabbing into a TextBox opens its tooltip (since .NET 4.8).
  • It doesn't comply with the latest accessibility requirements. For example, WCAG 2.1 requires that a tooltip is "hoverable" and "persistent", i.e. stays open while the user moves the mouse from the owning control to the tooltip (in order to move the scope of Magnifier to the tooltip).
  • It can re-open the Popup even after the ToolTip has closed. Because the storyboards only care about mouse position, and not about the state of the ToolTip.

The existing tooltip properties provide quite a bit of flexibility in controlling the behavior of the tooltip (and its Popup). You should use them, rather than styling Popup.

@dragnilar
Copy link

@SamBent FYI This problem affects third party components that change the behavior of the pop up (I.E. DevExpress). Should we make them aware of this issue or do you see this as something that can be addressed in WPF itself?

@SamBent
Copy link
Contributor

SamBent commented Jan 11, 2022

@dragnilar My PR will fix the crash (in WPF itself). WPF probably cannot address the other problems - if a third party overrides accessibility behavior, they are responsible for adapting to the latest requirements. So if you're having accessibility issues because DevExpress changes popup behavior, definitely make DevExpress aware.

That said, it's not always easy to know whether a given problem is caused by a third party, WPF, or the app itself. And when WPF changes accessibility behavior (or any behavior), we try not to break existing overrides and workarounds, but that's not always possible, and we usually don't even know what overrides and workarounds third parties are using. Thus we expect some bug reports that need our help to determine who is actually responsible, and (if it's a third party) whether WPF can or should adapt the behavior change to support the third party's usage.

@czdietrich
Copy link

As it turns out this fix seems not to make it into .NET 6.0.2. Is there any known workaround for this issue?

@haefele
Copy link

haefele commented Feb 7, 2022

A lot of our customers are also impacted by this bug. Is it possible this fix can still be included in the 6.0.2 version?

@czdietrich
Copy link

czdietrich commented Feb 7, 2022

Unfortunately not. 6.0.2 will come on Tuesday. So we have to hope for 6.0.3 in March.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.