hardcodet / wpf-notifyicon

NotifyIcon (aka system tray icon or taskbar icon) for the WPF platform
MIT License
861 stars 133 forks source link

The root Visual of a VisualTarget cannot have a parent. #44

Open ssolmer opened 4 years ago

ssolmer commented 4 years ago

NotifyIcon.Wpf.TaskbarNotification (.NET 4.0) v1.0.5.0

I get this exception when attempting to show a dialog window. There are other people on StackOverflow who have encountered this error as well. https://stackoverflow.com/q/28833702/2596334

 ExMessage   = The root Visual of a VisualTarget cannot have a parent.
 ExType      = System.ArgumentException
 StackTrace  =    at System.Windows.Media.CompositionTarget.SetRootVisual(Visual visual)  
    at System.Windows.Media.CompositionTarget.set_RootVisual(Visual value)
    at System.Windows.Interop.HwndTarget.set_RootVisual(Visual value)
    at System.Windows.Interop.HwndSource.set_RootVisualInternal(Visual value)
    at System.Windows.Interop.HwndSource.set_RootVisual(Visual value)
    at System.Windows.Controls.Primitives.Popup.SetRootVisualToPopupRoot()
    at System.Windows.Controls.Primitives.Popup.CreateWindow(Boolean asyncCall)
    at System.Windows.Controls.Primitives.Popup.OnIsOpenChanged(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.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
    at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
    at System.Windows.Data.BindingOperations.SetBinding(DependencyObject target, DependencyProperty dp, BindingBase binding)
    at System.Windows.Controls.Primitives.Popup.CreateRootPopup(Popup popup, UIElement child)
    at System.Windows.Controls.ToolTip.HookupParentPopup()
    at System.Windows.Controls.ToolTip.OnIsOpenChanged(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.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
    at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
    at Hardcodet.Wpf.TaskbarNotification.TaskbarIcon.OnToolTipChange(Boolean visible) in c:\git\OSS\notifyicon-wpf\Hardcodet.NotifyIcon.Wpf\Source\NotifyIconWpf\TaskbarIcon.cs:line 496
    at Hardcodet.Wpf.TaskbarNotification.Interop.WindowMessageSink.ProcessWindowMessage(UInt32 msg, IntPtr wParam, IntPtr lParam) in c:\git\OSS\notifyicon-wpf\Hardcodet.NotifyIcon.Wpf\Source\NotifyIconWpf\Interop\WindowMessageSink.cs:line 296
    at Hardcodet.Wpf.TaskbarNotification.Interop.WindowMessageSink.OnWindowMessageReceived(IntPtr hwnd, UInt32 messageId, IntPtr wparam, IntPtr lparam) in c:\git\OSS\notifyicon-wpf\Hardcodet.NotifyIcon.Wpf\Source\NotifyIconWpf\Interop\WindowMessageSink.cs:line 213
    at MS.Win32.UnsafeNativeMethods.ITfMessagePump.GetMessageW(MSG& msg, IntPtr hwnd, Int32 msgFilterMin, Int32 msgFilterMax, Int32& result)
    at System.Windows.Threading.Dispatcher.GetMessage(MSG& msg, IntPtr hwnd, Int32 minMessage, Int32 maxMessage)
    at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
    at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
    at System.Windows.Window.ShowHelper(Object booleanBox)
    at System.Windows.Window.Show()
    at System.Windows.Window.ShowDialog()
vegardlarsen commented 4 years ago

Edit! This doesn't work.

Having determined that this has to do with setting the tooltip before the taskbar icon has loaded properly (there are a lot of assumptions underlying this), I think I've solved this in my application. Instead of setting ToolTipText in XAML, I set it in the Loaded event of the associated window:

        private void Window_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {
            this.TrayIcon.ToolTipText = "Your tooltip";
        }

And then of course you need to do something like:

<Window ...
    Loaded="Window_Loaded">
samhocevar commented 4 years ago

Note that project Monitorian seems to have the same problem despite not using wpf-notifyicon and having their own wrapper around a WinForms icon instead (see their notify icon code here).

vegardlarsen commented 4 years ago

Thank you @samhocevar. It seems that posting my fix was premature, as the "same" error re-appeared in our crash logs a few hours afterwards. So my solution above does not work either.

iCodeSometime commented 3 years ago

I am getting this same error - but only occasionally.. Seems like a race condition somewhere