"'ToolTip' cannot have a logical or visual parent" error on chart zoom

TeeChart for Microsoft Visual Studio .NET, Xamarin Studio (Android, iOS & Forms) & Monodevelop.
Post Reply
jeffn
Newbie
Newbie
Posts: 3
Joined: Mon Feb 08, 2021 12:00 am

"'ToolTip' cannot have a logical or visual parent" error on chart zoom

Post by jeffn » Mon Feb 08, 2021 4:16 pm

Hello.
We have a client that is encountering an intermittent error that appears to be tied to zooming in on a WPF TChart and tooltip display.

We are using the Steema.TeeChart.Net nuget package at version 4.2019.7.3
Using the TChart control found in the Steema.TeeChart.WPF namespace.

The user reports that they will zoom in on an area of the chart by drawing a zoom rectangle around an area. When they release, the application crashes.

The unhandled application exception we are catching is reporting the following error and stack trace.

Code: Select all

System.InvalidOperationException: 'ToolTip' cannot have a logical or visual parent.
   at System.Windows.Controls.ToolTip.OnAncestorChanged()
   at System.Windows.FrameworkElement.OnAncestorChangedInternal(TreeChangeInfo parentTreeState)
   at System.Windows.TreeWalkHelper.OnAncestorChanged(DependencyObject d, TreeChangeInfo info, Boolean visitedViaVisualTree)
   at System.Windows.DescendentsWalker`1.StartWalk(DependencyObject startNode, Boolean skipStartNode)
   at MS.Internal.PrePostDescendentsWalker`1.StartWalk(DependencyObject startNode, Boolean skipStartNode)
   at System.Windows.TreeWalkHelper.InvalidateOnTreeChange(FrameworkElement fe, FrameworkContentElement fce, DependencyObject parent, Boolean isAddOperation)
   at System.Windows.FrameworkElement.ChangeLogicalParent(DependencyObject newParent)
   at System.Windows.FrameworkElement.RemoveLogicalChild(Object child)
   at System.Windows.LogicalTreeHelper.RemoveLogicalChild(DependencyObject parent, Object child)
   at System.Windows.Controls.ContentControl.OnContentChanged(Object oldContent, Object newContent)
   at System.Windows.Controls.ToolTip.OnContentChanged(Object oldContent, Object newContent)
   at System.Windows.Controls.ContentControl.OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
   at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
   at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
   at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
   at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
   at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue)
   at System.Windows.Data.BindingExpressionBase.Invalidate(Boolean isASubPropertyChange)
   at System.Windows.Data.BindingExpression.TransferValue(Object newValue, Boolean isASubPropertyChange)
   at System.Windows.Data.BindingExpression.ScheduleTransfer(Boolean isASubPropertyChange)
   at MS.Internal.Data.ClrBindingWorker.NewValueAvailable(Boolean dependencySourcesChanged, Boolean initialValue, Boolean isASubPropertyChange)
   at MS.Internal.Data.PropertyPathWorker.UpdateSourceValueState(Int32 k, ICollectionView collectionView, Object newValue, Boolean isASubPropertyChange)
   at MS.Internal.Data.PropertyPathWorker.OnDependencyPropertyChanged(DependencyObject d, DependencyProperty dp, Boolean isASubPropertyChange)
   at MS.Internal.Data.ClrBindingWorker.OnSourceInvalidation(DependencyObject d, DependencyProperty dp, Boolean isASubPropertyChange)
   at System.Windows.Data.BindingExpression.HandlePropertyInvalidation(DependencyObject d, DependencyPropertyChangedEventArgs args)
   at System.Windows.Data.BindingExpressionBase.OnPropertyInvalidation(DependencyObject d, DependencyPropertyChangedEventArgs args)
   at System.Windows.Data.BindingExpression.OnPropertyInvalidation(DependencyObject d, DependencyPropertyChangedEventArgs args)
   at System.Windows.DependentList.InvalidateDependents(DependencyObject source, DependencyPropertyChangedEventArgs sourceArgs)
   at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
   at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
   at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
   at System.Windows.Controls.ToolTipService.SetToolTip(DependencyObject element, Object value)
   at Steema.TeeChart.WPF.Chart.ChartToolTip.Show()
   at Steema.TeeChart.WPF.Tools.MarksTip.MouseEvent(MouseEventKinds kind, MouseEventArgs e, Cursor& c)
   at Steema.TeeChart.WPF.Chart.BroadcastMouseEvent(MouseEventKinds kind, MouseEventArgs e, Cursor& c)
   at Steema.TeeChart.WPF.Chart.BroadcastMouseEvent(MouseEventKinds kind, MouseEventArgs e, ModifierKeys modKeys, Cursor& c)
   at Steema.TeeChart.WPF.TChart.OnMouseMove(MouseEventArgs e)
   at System.Windows.UIElement.OnMouseMoveThunk(Object sender, MouseEventArgs e)
   at System.Windows.Input.MouseEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
   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.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run(Window window)
   at XXXX.XXXXXXXX.App.Main()

We are using the TeeChart to display real-time readings from sensor hardware, so points are being added to the graph very frequently for long periods of time. The users report that they have only seen this happen after a few hours of data being collected and displayed.

Unfortunately, we have been unable to reproduce this yet in our development environment so we do not have a small example application that exhibits the issue.

Any idea what is going on?

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: "'ToolTip' cannot have a logical or visual parent" error on chart zoom

Post by Christopher » Wed Feb 17, 2021 9:13 am

Hello,

many apologies for having missed this one. We are looking into it now and will get back to you as soon as possible.
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: "'ToolTip' cannot have a logical or visual parent" error on chart zoom

Post by Christopher » Wed Feb 17, 2021 10:43 am

Hello,

I've had a look at this, and it does seem a common error - I've found examples of it here, here, here, here, and here. Unfortunately we haven't been able to reproduce the issue.

TeeChart.WPF.dll calls the ToolTip via its ChartToolTip here:

Code: Select all

   at System.Windows.Controls.ToolTipService.SetToolTip(DependencyObject element, Object value)
   at Steema.TeeChart.WPF.Chart.ChartToolTip.Show()
   at Steema.TeeChart.WPF.Tools.MarksTip.MouseEvent(MouseEventKinds kind, MouseEventArgs e, Cursor& c)
Which means a MarksTip tool has to be present for it to be called - therefore the code I used to try and reproduce the issue is this:

Code: Select all

        private void InitializeChart(TChart tChart1)
        {
            var line = new Steema.TeeChart.WPF.Styles.Bar(tChart1.Chart);
            line.FillSampleValues();

            var marksTip = new MarksTip(tChart1.Chart);
            marksTip.Active = true;
            marksTip.MouseAction = MarksTipMouseAction.Move;
            marksTip.Series = line;
        }
I then moved the mouse around the chart to activate the ToolTip and then zoomed - I tried this for about four straight minutes without a problem.

I'm not at all sure what can be causing this problem to occur on your client's machine. I do believe, on the other hand, that it should not occur when the MarksTip tool is not present. It is worth bearing in mind that to Show and Hide the ToolTip instance of our ChartToolTip, we use the following code:

Code: Select all

            public void Show()
            {
                toolTip.Content = Text;
                toolTip.IsOpen = true;
                ToolTipService.SetToolTip(ChartControl, toolTip);
            }
			
			
            public void Hide()
            {
                toolTip.IsOpen = false;
                ToolTipService.SetToolTip(ChartControl, null);
            }
            
This may mean that if your client does not want to stop using the MarksTip tool, there maybe be a way to make a call to:

Code: Select all

ToolTipService.SetToolTip(ChartControl, null);
at a judicious point within their code.
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

jeffn
Newbie
Newbie
Posts: 3
Joined: Mon Feb 08, 2021 12:00 am

Re: "'ToolTip' cannot have a logical or visual parent" error on chart zoom

Post by jeffn » Wed Feb 17, 2021 4:19 pm

Thank you for taking a look at this Christopher.

Unfortunately I cannot completely remove the MarksTip from the chart, viewing tooltips for series points is an essential feature.

The users indicate that this seems to occur when they are zooming in on the chart. I'm thinking that if I could remove the MarksTip from the chart when they are starting the zoom, and add it back in when the zoom is complete then that might be an acceptable fix.
I only see events for Zoomed and UndoneZoom. Is there any way to be notified when a Zoom is about to happen so I can attempt to toggle the tooltip off at the start of the zoom, and then off when the zoom is complete?

Also, I noticed a difference in how you are adding the MarksTip to the chart in your sample code as compared to my own.
You are creating the MarksTip and associating it to a particular Series.
In our code we are creating the MarksTip and adding it to the TeeChart Tools collection,

var marksTip = new MarksTip(TChart.Chart) { Style = MarksStyles.XY };
TChart.Tools.Add(marksTip);


Our chart has one or more series being displayed at any given time (the user can add/remove a series at will). Having just the one MarksTip appears to work just fine for this, however I'm curious if it makes any difference and/or might be part of the problem.

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: "'ToolTip' cannot have a logical or visual parent" error on chart zoom

Post by Christopher » Wed Feb 17, 2021 5:48 pm

Hello!
jeffn wrote:
Wed Feb 17, 2021 4:19 pm
Having just the one MarksTip appears to work just fine for this, however I'm curious if it makes any difference and/or might be part of the problem.
The route through the code is very similar for specifying a series or not (if one is not specified, it runs the same code over them all) - I think the problem is in the showing and hiding of the WPF's (not Steema's) ToolTip itself, which is identical in both cases.
jeffn wrote:
Wed Feb 17, 2021 4:19 pm
Is there any way to be notified when a Zoom is about to happen so I can attempt to toggle the tooltip off at the start of the zoom, and then off when the zoom is complete?
Yes, I think there is - this code should do it:

Code: Select all

        private void InitializeChart(TChart tChart1)
        {
            var marksTip = new MarksTip(tChart1.Chart);

            void TChart1_MouseMove(object sender, MouseEventArgs e)
            {
                if(tChart1.Zoom.Active)
                {
                    tChart1.Chart.ToolTip.Hide();
                    marksTip.Active = false;
                }
                else
                {
                    if(!marksTip.Active)
                    {
                        marksTip.Active = true;
                    }
                }
            }

            tChart1.MouseMove += TChart1_MouseMove;

            var line = new Steema.TeeChart.WPF.Styles.Bar(tChart1.Chart);
            line.FillSampleValues();

            marksTip.Active = true;
            marksTip.MouseAction = MarksTipMouseAction.Move;
        }
The Zoom.Active is set to true on the mousedown event of TChart, if Zoom.Direction is not None, the correct mouse button is pressed and so on, which means that if the mousemouse event is fired when this is true that it's likely to be a Zoom action. Similarly, on the mouseup TChart event checks are made, the Zoom action is performed in the code (changing axes positions, basically) and Zoom.Active is set to false. So when Zoom.Active is true, we set the parent of the ToolTip to null via the ToolTip.Hide() method, and also set the marksTip.Active to false to stop it showing any more ToolTips, and when Zoom.Active is false we set marksTip.Active to true which means on the next mousemove (with the marksTip.MouseAction set to Move) ToolTips will be shown as necessary.

Unfortunately I can't guarantee this will stop your client's error - if it doesn't, we'll have to have another think.
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

jeffn
Newbie
Newbie
Posts: 3
Joined: Mon Feb 08, 2021 12:00 am

Re: "'ToolTip' cannot have a logical or visual parent" error on chart zoom

Post by jeffn » Wed Feb 17, 2021 7:31 pm

Thanks so much Christoper. I've implemented your code and it works as described.
Hopefully this will resolve the problem, I'll keep you posted.

Post Reply