Przeglądaj źródła

clean event subscriptions before updating menus.

Dan Walmsley 5 lat temu
rodzic
commit
6895ea9dd0

+ 5 - 2
src/Avalonia.Native/AvaloniaNativeMenuExporter.cs

@@ -16,6 +16,7 @@ namespace Avalonia.Native
         private IAvnWindow _nativeWindow;
         private NativeMenu _menu;
         private IAvnAppMenu _nativeMenu;
+        private IDisposable _disposable;
 
         public AvaloniaNativeMenuExporter(IAvnWindow nativeWindow, IAvaloniaNativeFactory factory)
         {
@@ -129,7 +130,8 @@ namespace Avalonia.Native
 
             menuItem.Menu = menu;
 
-            _nativeMenu.Update(this, _factory, appMenuHolder);
+            _disposable?.Dispose();
+            _disposable = _nativeMenu.Update(this, _factory, appMenuHolder);
 
             _factory.SetAppMenu(_nativeMenu);
         }
@@ -146,7 +148,8 @@ namespace Avalonia.Native
                 }
             }
 
-            _nativeMenu.Update(this, _factory, menu);
+            _disposable?.Dispose();
+            _disposable = _nativeMenu.Update(this, _factory, menu);
 
             avnWindow.SetMainMenu(_nativeMenu);
         }

+ 9 - 2
src/Avalonia.Native/IAvnAppMenu.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Collections.Specialized;
+using System.Reactive.Disposables;
 using Avalonia.Controls;
 using Avalonia.Platform.Interop;
 
@@ -42,8 +43,10 @@ namespace Avalonia.Native.Interop
             return nativeItem;
         }
 
-        internal void Update(AvaloniaNativeMenuExporter exporter, IAvaloniaNativeFactory factory, NativeMenu menu, string title = "")
+        internal IDisposable Update(AvaloniaNativeMenuExporter exporter, IAvaloniaNativeFactory factory, NativeMenu menu, string title = "")
         {
+            var disposables = new CompositeDisposable();
+
             if (_menu == null)
             {
                 _menu = menu;
@@ -57,6 +60,8 @@ namespace Avalonia.Native.Interop
 
             ((INotifyCollectionChanged)_menu.Items).CollectionChanged += IAvnAppMenu_CollectionChanged;
 
+            disposables.Add(Disposable.Create(() => ((INotifyCollectionChanged)_menu.Items).CollectionChanged -= IAvnAppMenu_CollectionChanged));
+
             if (!string.IsNullOrWhiteSpace(title))
             {
                 using (var buffer = new Utf8Buffer(title))
@@ -88,7 +93,7 @@ namespace Avalonia.Native.Interop
 
                 if (menu.Items[i] is NativeMenuItem nmi)
                 {
-                    nativeItem.Update(exporter, factory, nmi);
+                    disposables.Add(nativeItem.Update(exporter, factory, nmi));
                 }
                         
                 InsertAt(i, nativeItem);
@@ -98,6 +103,8 @@ namespace Avalonia.Native.Interop
             {
                 Remove(_menuItems[i]);
             }
+
+            return disposables;
         }
 
         private void IAvnAppMenu_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)

+ 12 - 3
src/Avalonia.Native/IAvnAppMenuItem.cs

@@ -1,4 +1,6 @@
-using Avalonia.Controls;
+using System;
+using System.Reactive.Disposables;
+using Avalonia.Controls;
 using Avalonia.Platform.Interop;
 
 namespace Avalonia.Native.Interop
@@ -10,14 +12,18 @@ namespace Avalonia.Native.Interop
 
         public NativeMenuItemBase Managed { get; set; }
 
-        internal void Update(AvaloniaNativeMenuExporter exporter, IAvaloniaNativeFactory factory, NativeMenuItem item)
+        internal IDisposable Update(AvaloniaNativeMenuExporter exporter, IAvaloniaNativeFactory factory, NativeMenuItem item)
         {
+            var disposables = new CompositeDisposable();
+
             _exporter = exporter;
 
             Managed = item;
 
             Managed.PropertyChanged += Item_PropertyChanged;
 
+            disposables.Add(Disposable.Create(() => Managed.PropertyChanged -= Item_PropertyChanged));
+
             if(!string.IsNullOrWhiteSpace(item.Header))
             {
                 using (var buffer = new Utf8Buffer(item.Header))
@@ -52,7 +58,8 @@ namespace Avalonia.Native.Interop
                 }
 
                 SetSubMenu(_subMenu);
-                _subMenu.Update(exporter, factory, item.Menu, item.Header);
+                
+                disposables.Add(_subMenu.Update(exporter, factory, item.Menu, item.Header));
             }
 
             if (item.Menu == null && _subMenu != null)
@@ -61,6 +68,8 @@ namespace Avalonia.Native.Interop
 
                 // needs implementing on native side also.
             }
+
+            return disposables;
         }
 
         private void Item_PropertyChanged(object sender, AvaloniaPropertyChangedEventArgs e)