Browse Source

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.
pull/3745/head
Steven Kirk 6 years ago
parent
commit
76b4d17abf
  1. 41
      src/Avalonia.Controls/ContextMenu.cs

41
src/Avalonia.Controls/ContextMenu.cs

@ -20,6 +20,7 @@ namespace Avalonia.Controls
private static readonly ITemplate<IPanel> DefaultPanel =
new FuncTemplate<IPanel>(() => new StackPanel { Orientation = Orientation.Vertical });
private Popup _popup;
private bool _attachedToControl;
/// <summary>
/// Initializes a new instance of the <see cref="ContextMenu"/> 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<MenuItem>())
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)

Loading…
Cancel
Save