Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Button.IsCancel still works for detached button + MemoryLeak #7751

Closed
jinek opened this issue Mar 5, 2022 · 6 comments · Fixed by #8253
Closed

Button.IsCancel still works for detached button + MemoryLeak #7751

jinek opened this issue Mar 5, 2022 · 6 comments · Fixed by #8253
Labels
bug help-wanted A contribution from the community would be most welcome.

Comments

@jinek
Copy link
Contributor

jinek commented Mar 5, 2022

Describe the bug
Button.StopListeningForCancel is called only when property IsCancel is set to false and is not called when button is detached from the visual tree.
Additionally that also means that root element holds reference to the button forewer:

        private void ListenForCancel(IInputElement root)
        {
            root.AddHandler(KeyDownEvent, RootCancelKeyDown);
        }
  • Version 0.10.12
@jinek jinek added the bug label Mar 5, 2022
@robloo
Copy link
Contributor

robloo commented Mar 5, 2022

Note: This issue would also apply for IsDefault

I can't speak for the correctness of your solution. However, it should be easy to add the code from the OnPropertyChanged method here:

protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
if (_hotkey != null) // Control attached again, set Hotkey to create a hotkey manager for this control
{
HotKey = _hotkey;
}
base.OnAttachedToLogicalTree(e);
if (Command != null)
{
Command.CanExecuteChanged += CanExecuteChanged;
CanExecuteChanged(this, EventArgs.Empty);
}
}
/// <inheritdoc/>
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
{
// This will cause the hotkey manager to dispose the observer and the reference to this control
if (HotKey != null)
{
_hotkey = HotKey;
HotKey = null;
}
base.OnDetachedFromLogicalTree(e);
if (Command != null)
{
Command.CanExecuteChanged -= CanExecuteChanged;
}
}

@jinek
Copy link
Contributor Author

jinek commented Mar 5, 2022

Note: This issue would also apply for IsDefault

I can't speak for the correctness of your solution. However, it should be easy to add the code from the OnPropertyChanged method here:

protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
if (_hotkey != null) // Control attached again, set Hotkey to create a hotkey manager for this control
{
HotKey = _hotkey;
}
base.OnAttachedToLogicalTree(e);
if (Command != null)
{
Command.CanExecuteChanged += CanExecuteChanged;
CanExecuteChanged(this, EventArgs.Empty);
}
}
/// <inheritdoc/>
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
{
// This will cause the hotkey manager to dispose the observer and the reference to this control
if (HotKey != null)
{
_hotkey = HotKey;
HotKey = null;
}
base.OnDetachedFromLogicalTree(e);
if (Command != null)
{
Command.CanExecuteChanged -= CanExecuteChanged;
}
}

Now I'm thinking may be that is conceptual issue? May be events automatically should unsubsribe when element is detached?

@robloo
Copy link
Contributor

robloo commented Mar 6, 2022

We'll need someone from the core team to weigh-in with how things are supposed to work. At first glance, it appears you are correct though and the button should be automatically unsubscribing when adding/removing from the logical tree -- not only when the property value changes. The Command is already handled this way.

Code I would be looking to add to OnAttached/DetachedLogicalTree (or perhaps VisualTree) methods is from the OnPropertyChanged method:

if (VisualRoot is IInputElement inputRoot)
{
if (isCancel)
{
ListenForCancel(inputRoot);
}
else
{
StopListeningForCancel(inputRoot);
}
}

@maxkatz6
Copy link
Member

Yes. Subscribing and unsubscribing should be done in OnAttached/Detached methods.
We can find it was already done for IsDefault and IsCancel in OnAttachedToVisualTree/OnDetachedFromVisualTree.
But cleanup is done only for IsDefault, IsCancel was missed. See https://github.com/AvaloniaUI/Avalonia/blame/master/src/Avalonia.Controls/Button.cs#L228-L234

@maxkatz6
Copy link
Member

Solution is to unsubscribe IsCancel in OnDetachedFromVisualTree method.

@maxkatz6 maxkatz6 added the help-wanted A contribution from the community would be most welcome. label Apr 17, 2022
@robloo
Copy link
Contributor

robloo commented Apr 18, 2022

@maxkatz6 Thanks for confirming. Since I've done some work with Button recently and know my way around this code I'll fix this one. No guarantees on timing but it will be done before 11.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug help-wanted A contribution from the community would be most welcome.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants