diff --git a/src/Avalonia.Native/IAvnAppMenu.cs b/src/Avalonia.Native/IAvnAppMenu.cs index 0d4c4f55e4..412980c2c4 100644 --- a/src/Avalonia.Native/IAvnAppMenu.cs +++ b/src/Avalonia.Native/IAvnAppMenu.cs @@ -23,6 +23,8 @@ namespace Avalonia.Native.Interop item.Update(null, null, null); RemoveItem(item); + item.Deinitialise(); + item.Dispose(); } @@ -35,12 +37,18 @@ namespace Avalonia.Native.Interop InsertItem(index, item); } - private void InsertNewAt(int index, IAvnAppMenuItem item) + private IAvnAppMenuItem CreateNewAt(IAvaloniaNativeFactory factory, int index, NativeMenuItemBase item) { - _menuItemLookup.Add(item.ManagedMenuItem, item); - _menuItems.Insert(index, item); + var result = CreateNew(factory, item); - InsertItem(index, item); + result.Initialise(); + + _menuItemLookup.Add(result.ManagedMenuItem, result); + _menuItems.Insert(index, result); + + InsertItem(index, result); + + return result; } private IAvnAppMenuItem CreateNew(IAvaloniaNativeFactory factory, NativeMenuItemBase item) @@ -84,9 +92,7 @@ namespace Avalonia.Native.Interop if (i >= _menuItems.Count) { - nativeItem = CreateNew(factory, menu.Items[i]); - - InsertNewAt(i, nativeItem); + nativeItem = CreateNewAt(factory, i, menu.Items[i]); } else if (menu.Items[i] == _menuItems[i].ManagedMenuItem) { @@ -98,9 +104,7 @@ namespace Avalonia.Native.Interop } else { - nativeItem = CreateNew(factory, menu.Items[i]); - - InsertNewAt(i, nativeItem); + nativeItem = CreateNewAt(factory, i, menu.Items[i]); } if (menu.Items[i] is NativeMenuItem nmi) diff --git a/src/Avalonia.Native/IAvnAppMenuItem.cs b/src/Avalonia.Native/IAvnAppMenuItem.cs index 281edc26cf..1dff5ff875 100644 --- a/src/Avalonia.Native/IAvnAppMenuItem.cs +++ b/src/Avalonia.Native/IAvnAppMenuItem.cs @@ -10,7 +10,7 @@ namespace Avalonia.Native.Interop private IAvnAppMenu _subMenu; private AvaloniaNativeMenuExporter _exporter; private CompositeDisposable _propertyDisposables = new CompositeDisposable(); - private PredicateCallback _currentAction; + private IDisposable _currentActionDisposable; public NativeMenuItemBase ManagedMenuItem { get; set; } @@ -33,9 +33,9 @@ namespace Avalonia.Native.Interop private void UpdateAction (NativeMenuItem item) { - _currentAction?.Dispose(); + _currentActionDisposable?.Dispose(); - SetAction(new PredicateCallback(() => + var action = new PredicateCallback(() => { if (item.Command != null || item.HasClickHandlers) { @@ -43,7 +43,41 @@ namespace Avalonia.Native.Interop } return false; - }), new MenuActionCallback(() => { item.RaiseClick(); })); + }); + + var callback = new MenuActionCallback(() => { item.RaiseClick(); }); + + _currentActionDisposable = Disposable.Create(() => + { + action.Dispose(); + callback.Dispose(); + }); + + SetAction(action, callback); + } + + internal void Initialise() + { + _propertyDisposables.Add(Disposable.Create(() => ManagedMenuItem.GetObservable(NativeMenuItem.HeaderProperty) + .Subscribe(x => UpdateTitle(x)))); + + _propertyDisposables.Add(Disposable.Create(() => ManagedMenuItem.GetObservable(NativeMenuItem.GestureProperty) + .Subscribe(x => UpdateGesture(x)))); + + _propertyDisposables.Add(Disposable.Create(() => ManagedMenuItem.GetObservable(NativeMenuItem.CommandProperty) + .Subscribe(x => UpdateAction(ManagedMenuItem as NativeMenuItem)))); + } + + internal void Deinitialise () + { + if(_subMenu != null) + { + _subMenu.Update(null, null, null); + _subMenu = null; + } + + _propertyDisposables?.Dispose(); + _currentActionDisposable?.Dispose(); } internal IDisposable Update(AvaloniaNativeMenuExporter exporter, IAvaloniaNativeFactory factory, NativeMenuItem item) @@ -54,19 +88,10 @@ namespace Avalonia.Native.Interop ManagedMenuItem = item; - _propertyDisposables.Add(Disposable.Create(() => ManagedMenuItem.GetObservable(NativeMenuItem.HeaderProperty) - .Subscribe(x => UpdateTitle(x)))); - UpdateTitle(item.Header); - _propertyDisposables.Add(Disposable.Create(() => ManagedMenuItem.GetObservable(NativeMenuItem.GestureProperty) - .Subscribe(x => UpdateGesture(x)))); - UpdateGesture(item.Gesture); - _propertyDisposables.Add(Disposable.Create(() => ManagedMenuItem.GetObservable(NativeMenuItem.CommandProperty) - .Subscribe(x => UpdateAction(ManagedMenuItem as NativeMenuItem)))); - UpdateAction(ManagedMenuItem as NativeMenuItem); if (item.Menu != null)