Fix ComboBox memory leak

This commit is contained in:
chinboy
2025-03-01 15:52:47 +08:00
parent 5481e71082
commit ce8530c41e
3 changed files with 57 additions and 33 deletions
+20 -2
View File
@@ -1,10 +1,12 @@
using AtomUI.Data;
using System.Reactive.Disposables;
using AtomUI.Data;
using AtomUI.Theme;
using AtomUI.Theme.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Layout;
using Avalonia.LogicalTree;
namespace AtomUI.Controls;
@@ -12,7 +14,8 @@ using AvaloniaComboBox = Avalonia.Controls.ComboBox;
public class ComboBox : AvaloniaComboBox,
IAnimationAwareControl,
IControlSharedTokenResourcesHost
IControlSharedTokenResourcesHost,
ITokenResourceConsumer
{
public const string ErrorPC = ":error";
public const string WarningPC = ":warning";
@@ -116,8 +119,11 @@ public class ComboBox : AvaloniaComboBox,
Control IAnimationAwareControl.PropertyBindTarget => this;
Control IControlSharedTokenResourcesHost.HostControl => this;
string IControlSharedTokenResourcesHost.TokenId => ComboBoxToken.ID;
CompositeDisposable? ITokenResourceConsumer.TokenBindingsDisposable => _tokenBindingsDisposable;
#endregion
private CompositeDisposable? _tokenBindingsDisposable;
static ComboBox()
{
@@ -187,4 +193,16 @@ public class ComboBox : AvaloniaComboBox,
PseudoClasses.Set(ErrorPC, Status == AddOnDecoratedStatus.Error);
PseudoClasses.Set(WarningPC, Status == AddOnDecoratedStatus.Warning);
}
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnAttachedToLogicalTree(e);
_tokenBindingsDisposable = new CompositeDisposable();
}
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnDetachedFromLogicalTree(e);
this.DisposeTokenBindings();
}
}
@@ -1,17 +1,19 @@
using AtomUI.Theme.Data;
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using Avalonia;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Data;
using Avalonia.LogicalTree;
using Avalonia.Media;
using Avalonia.Rendering;
namespace AtomUI.Controls;
[TemplatePart(ComboBoxSpinnerInnerBoxTheme.SpinnerHandlePart, typeof(ContentPresenter))]
internal class ComboBoxSpinnerInnerBox : AddOnDecoratedInnerBox, ICustomHitTest
internal class ComboBoxSpinnerInnerBox : AddOnDecoratedInnerBox,
ICustomHitTest
{
#region 公共属性定义
@@ -81,15 +83,15 @@ internal class ComboBoxSpinnerInnerBox : AddOnDecoratedInnerBox, ICustomHitTest
return true;
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
TokenResourceBinder.CreateTokenBinding(this, SpinnerBorderThicknessProperty,
base.OnAttachedToLogicalTree(e);
this.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(this, SpinnerBorderThicknessProperty,
SharedTokenKey.BorderThickness, BindingPriority.Template,
new RenderScaleAwareThicknessConfigure(this));
TokenResourceBinder.CreateTokenBinding(this, SpinnerBorderBrushProperty,
SharedTokenKey.ColorBorder);
TokenResourceBinder.CreateTokenBinding(this, SpinnerHandleWidthTokenProperty,
ButtonSpinnerTokenKey.HandleWidth);
base.OnApplyTemplate(e);
new RenderScaleAwareThicknessConfigure(this)));
this.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(this, SpinnerBorderBrushProperty,
SharedTokenKey.ColorBorder));
this.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(this, SpinnerHandleWidthTokenProperty,
ButtonSpinnerTokenKey.HandleWidth));
}
}
+24 -20
View File
@@ -101,10 +101,12 @@ internal class ComboBoxTheme : BaseControlTheme
var decreaseButtonIcon = AntDesignIconPackage.DownOutlined();
TokenResourceBinder.CreateTokenBinding(decreaseButtonIcon, Icon.ActiveFilledBrushProperty,
ButtonSpinnerTokenKey.HandleHoverColor);
TokenResourceBinder.CreateTokenBinding(decreaseButtonIcon, Icon.SelectedFilledBrushProperty,
SharedTokenKey.ColorPrimaryActive);
comboBox.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(decreaseButtonIcon,
Icon.ActiveFilledBrushProperty,
ButtonSpinnerTokenKey.HandleHoverColor));
comboBox.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(decreaseButtonIcon,
Icon.SelectedFilledBrushProperty,
SharedTokenKey.ColorPrimaryActive));
var openButton = new IconButton
{
@@ -117,12 +119,14 @@ internal class ComboBoxTheme : BaseControlTheme
openButton.RegisterInNameScope(scope);
TokenResourceBinder.CreateTokenBinding(openButton, Layoutable.WidthProperty,
ComboBoxTokenKey.OpenIndicatorWidth);
TokenResourceBinder.CreateTokenBinding(openButton, IconButton.IconWidthProperty,
SharedTokenKey.IconSizeSM);
TokenResourceBinder.CreateTokenBinding(openButton, IconButton.IconHeightProperty,
SharedTokenKey.IconSizeSM);
comboBox.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(openButton, Layoutable.WidthProperty,
ComboBoxTokenKey.OpenIndicatorWidth));
comboBox.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(openButton,
IconButton.IconWidthProperty,
SharedTokenKey.IconSizeSM));
comboBox.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(openButton,
IconButton.IconHeightProperty,
SharedTokenKey.IconSizeSM));
spinnerHandleDecorator.Child = openButton;
spinnerInnerBox.SpinnerContent = spinnerHandleDecorator;
@@ -179,12 +183,12 @@ internal class ComboBoxTheme : BaseControlTheme
var border = new Border();
TokenResourceBinder.CreateTokenBinding(border, Border.BackgroundProperty,
SharedTokenKey.ColorBgContainer);
TokenResourceBinder.CreateTokenBinding(border, Border.CornerRadiusProperty,
ComboBoxTokenKey.PopupBorderRadius);
TokenResourceBinder.CreateTokenBinding(border, Decorator.PaddingProperty,
ComboBoxTokenKey.PopupContentPadding);
comboBox.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(border, Border.BackgroundProperty,
SharedTokenKey.ColorBgContainer));
comboBox.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(border, Border.CornerRadiusProperty,
ComboBoxTokenKey.PopupBorderRadius));
comboBox.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(border, Decorator.PaddingProperty,
ComboBoxTokenKey.PopupContentPadding));
var scrollViewer = new MenuScrollViewer();
var itemsPresenter = new ItemsPresenter
@@ -198,10 +202,10 @@ internal class ComboBoxTheme : BaseControlTheme
popup.Child = border;
TokenResourceBinder.CreateTokenBinding(popup, Popup.MarginToAnchorProperty,
ComboBoxTokenKey.PopupMarginToAnchor);
TokenResourceBinder.CreateTokenBinding(popup, Popup.MaskShadowsProperty,
ComboBoxTokenKey.PopupBoxShadows);
comboBox.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(popup, Popup.MarginToAnchorProperty,
ComboBoxTokenKey.PopupMarginToAnchor));
comboBox.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(popup, Popup.MaskShadowsProperty,
ComboBoxTokenKey.PopupBoxShadows));
CreateTemplateParentBinding(popup, Layoutable.MaxHeightProperty,
ComboBox.MaxDropDownHeightProperty);
CreateTemplateParentBinding(popup, Avalonia.Controls.Primitives.Popup.IsOpenProperty,