diff --git a/src/Avalonia.Controls/Platform/ITrayIconImpl.cs b/src/Avalonia.Controls/Platform/ITrayIconImpl.cs
index e1eb62821b..013aff13ee 100644
--- a/src/Avalonia.Controls/Platform/ITrayIconImpl.cs
+++ b/src/Avalonia.Controls/Platform/ITrayIconImpl.cs
@@ -6,7 +6,7 @@ using Avalonia.Controls.Platform;
namespace Avalonia.Platform
{
- public interface ITrayIconImpl
+ public interface ITrayIconImpl : IDisposable
{
///
/// Sets the icon of this tray icon.
diff --git a/src/Avalonia.Controls/TrayIcon.cs b/src/Avalonia.Controls/TrayIcon.cs
index 8f422dd4d4..dfa71dcb1e 100644
--- a/src/Avalonia.Controls/TrayIcon.cs
+++ b/src/Avalonia.Controls/TrayIcon.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using Avalonia.Collections;
+using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls.Platform;
using Avalonia.Platform;
@@ -12,7 +13,7 @@ namespace Avalonia.Controls
{
}
- public class TrayIcon : AvaloniaObject, IDataContextProvider, INativeMenuExporterProvider
+ public class TrayIcon : AvaloniaObject, IDataContextProvider, INativeMenuExporterProvider, IDisposable
{
private readonly ITrayIconImpl _impl;
@@ -44,6 +45,21 @@ namespace Avalonia.Controls
}
}
});
+
+ if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime lifetime)
+ {
+ lifetime.Exit += Lifetime_Exit;
+ }
+ }
+
+ private static void Lifetime_Exit(object sender, ControlledApplicationLifetimeExitEventArgs e)
+ {
+ var trayIcons = GetTrayIcons(Application.Current);
+
+ foreach(var icon in trayIcons)
+ {
+ icon.Dispose();
+ }
}
private static void Icons_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
@@ -84,6 +100,7 @@ namespace Avalonia.Controls
///
public static readonly StyledProperty IsVisibleProperty =
Visual.IsVisibleProperty.AddOwner();
+ private bool _disposedValue;
public static void SetTrayIcons(AvaloniaObject o, TrayIcons trayIcons) => o.SetValue(TrayIconsProperty, trayIcons);
@@ -160,5 +177,7 @@ namespace Avalonia.Controls
_impl.SetToolTipText(change.NewValue.GetValueOrDefault());
}
}
+
+ public void Dispose() => _impl.Dispose();
}
}
diff --git a/src/Avalonia.DesignerSupport/Remote/TrayIconStub.cs b/src/Avalonia.DesignerSupport/Remote/TrayIconStub.cs
index 13d38660eb..6fd70f203c 100644
--- a/src/Avalonia.DesignerSupport/Remote/TrayIconStub.cs
+++ b/src/Avalonia.DesignerSupport/Remote/TrayIconStub.cs
@@ -13,6 +13,11 @@ namespace Avalonia.DesignerSupport.Remote
public INativeMenuExporter MenuExporter => throw new NotImplementedException();
+ public void Dispose()
+ {
+ throw new NotImplementedException();
+ }
+
public void SetIcon(IWindowIconImpl icon)
{
}
diff --git a/src/Windows/Avalonia.Win32/TrayIconImpl.cs b/src/Windows/Avalonia.Win32/TrayIconImpl.cs
index cdd0c3a2f6..c1286f8436 100644
--- a/src/Windows/Avalonia.Win32/TrayIconImpl.cs
+++ b/src/Windows/Avalonia.Win32/TrayIconImpl.cs
@@ -25,6 +25,7 @@ namespace Avalonia.Win32
private readonly Win32NativeToManagedMenuExporter _exporter;
private static Dictionary s_trayIcons = new Dictionary();
+ private bool _disposedValue;
public INativeMenuExporter MenuExporter => _exporter;
@@ -45,12 +46,6 @@ namespace Avalonia.Win32
s_trayIcons.Add(_uniqueId, this);
}
-
- ~TrayIconImpl()
- {
- UpdateIcon(false);
- }
-
public void SetIcon(IWindowIconImpl? icon)
{
_icon = icon as IconImpl;
@@ -258,5 +253,28 @@ namespace Avalonia.Win32
public virtual double Scaling => _hiddenWindow.Screens.Primary.PixelDensity;
}
}
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposedValue)
+ {
+ UpdateIcon(true);
+
+ _disposedValue = true;
+ }
+ }
+
+ ~TrayIconImpl()
+ {
+ // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
+ Dispose(disposing: false);
+ }
+
+ public void Dispose()
+ {
+ // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
}
}