From 6895ea9dd0eb11511e819d10a36c86ea422468fc Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 9 Apr 2020 13:28:15 -0300 Subject: [PATCH] clean event subscriptions before updating menus. --- src/Avalonia.Native/AvaloniaNativeMenuExporter.cs | 7 +++++-- src/Avalonia.Native/IAvnAppMenu.cs | 11 +++++++++-- src/Avalonia.Native/IAvnAppMenuItem.cs | 15 ++++++++++++--- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs b/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs index 86fce67ed0..c071456cf4 100644 --- a/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs +++ b/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); } diff --git a/src/Avalonia.Native/IAvnAppMenu.cs b/src/Avalonia.Native/IAvnAppMenu.cs index c44100ae2a..eb75c6f86b 100644 --- a/src/Avalonia.Native/IAvnAppMenu.cs +++ b/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) diff --git a/src/Avalonia.Native/IAvnAppMenuItem.cs b/src/Avalonia.Native/IAvnAppMenuItem.cs index c35a796b59..55797449f1 100644 --- a/src/Avalonia.Native/IAvnAppMenuItem.cs +++ b/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)