From 76b4d17abf0de768fc9504fc1b8ef9967466429c Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 3 Apr 2020 23:21:06 +0200 Subject: [PATCH] Remove ContextMenu from logical tree. When the `ContextMenu` is not attached to a control, i.e. it is shown using `Show(control)` then we need to detach it from the logical tree once hidden otherwise it will leak, causing #3738. --- src/Avalonia.Controls/ContextMenu.cs | 41 ++++++++++++++-------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/Avalonia.Controls/ContextMenu.cs b/src/Avalonia.Controls/ContextMenu.cs index fc56e26add..0ee906fb55 100644 --- a/src/Avalonia.Controls/ContextMenu.cs +++ b/src/Avalonia.Controls/ContextMenu.cs @@ -20,6 +20,7 @@ namespace Avalonia.Controls private static readonly ITemplate DefaultPanel = new FuncTemplate(() => new StackPanel { Orientation = Orientation.Vertical }); private Popup _popup; + private bool _attachedToControl; /// /// Initializes a new instance of the class. @@ -69,13 +70,15 @@ namespace Avalonia.Controls { var control = (Control)e.Sender; - if (e.OldValue != null) + if (e.OldValue is ContextMenu oldMenu) { control.PointerReleased -= ControlPointerReleased; + oldMenu._attachedToControl = false; } - if (e.NewValue != null) + if (e.NewValue is ContextMenu newMenu) { + newMenu._attachedToControl = true; control.PointerReleased += ControlPointerReleased; } } @@ -145,18 +148,6 @@ namespace Avalonia.Controls return new MenuItemContainerGenerator(this); } - private void CloseCore() - { - SelectedIndex = -1; - IsOpen = false; - - RaiseEvent(new RoutedEventArgs - { - RoutedEvent = MenuClosedEvent, - Source = this, - }); - } - private void PopupOpened(object sender, EventArgs e) { Focus(); @@ -164,17 +155,27 @@ namespace Avalonia.Controls private void PopupClosed(object sender, EventArgs e) { - var contextMenu = (sender as Popup)?.Child as ContextMenu; - - if (contextMenu != null) + foreach (var i in LogicalChildren) { - foreach (var i in contextMenu.GetLogicalChildren().OfType()) + if (i is MenuItem menuItem) { - i.IsSubMenuOpen = false; + menuItem.IsSubMenuOpen = false; } + } + + SelectedIndex = -1; + IsOpen = false; - contextMenu.CloseCore(); + if (!_attachedToControl) + { + ((ISetLogicalParent)_popup).SetParent(null); } + + RaiseEvent(new RoutedEventArgs + { + RoutedEvent = MenuClosedEvent, + Source = this, + }); } private static void ControlPointerReleased(object sender, PointerReleasedEventArgs e)