Same pattern as WindowNotificationManager fix (1e851b13):
- Add OnClose internal property to MessageCard to carry the per-message
callback without capturing local variables from Show()
- Replace MessageClosed lambda with instance method OnMessageClosed
(accesses _items via 'this', no local variable capture)
- Add OnClick/OnClose internal properties to NotificationCard to carry
per-notification callbacks without capturing local variables
- Replace PointerPressed lambda with static OnNotificationPointerPressed
(zero closure allocation, reads callback from card.OnClick)
- Replace NotificationClosed lambda with instance OnNotificationClosed
(accesses _items via 'this', no local variable capture)
- Update AtomUI_issues.md: mark 1.2 as fixed, remove from P8 list
Modal methods (ShowMessageBoxModalAsync, ShowMessageModalAsync,
ShowDialogModalAsync x2): OpenAsync() awaits dialog close, so cleanup
is moved after await tsc.Task — no Closed subscription needed.
Non-modal methods (ShowMessageBoxAsync, ShowMessageAsync,
ShowDialogAsync x2): OpenAsync() returns after dialog is shown, so
Closed lambda is retained as the only close notification point.
The lambda is harmless: Closed fires exactly once, dialog is removed
from parent and GC'd immediately after, releasing the closure.
- Update AtomUI_issues.md: mark 1.1 as fixed, remove from P3 list
- Delete performance_memory_leak.md (tracking moved to AtomUI_issues.md)
- INotifyTransitionCompleted interface now extends IDisposable
- AbstractNotifiableTransition<T>.Dispose() disposes Subject<bool> and nulls it
- NotifyTransitionCompleted() guards against null _subject (post-dispose)
- CompletedObservable throws ObjectDisposedException if accessed after Dispose
- AbstractMotion.RunTransitions: dispose all Transitions after await completes
(covers both normal completion and Task.Delay timeout path)
- AbstractMotion.ConfigureTransitions: dispose existing Transitions before Clear
to prevent Subject leaks when transitions are rebuilt
- Update performance_memory_leak.md: 32/39 fixed (82.1%), High 8/8 all done
Items is an internal ItemCollection owned by Form with identical lifetime.
The subscription cannot leak across lifetimes: when Form is GC'd, Items and
its event subscriptions are collected with it. Mark 3.4 as false positive in docs.
- Replace anonymous lambda with named method to allow precise -= unsubscription
- Prevents subscription leak when Items is replaced by an external CollectionView
- Update performance_memory_leak.md: 32/39 fixed (82.1%), Medium 16/19
- Mirror the same WeakCollectionChangedForwarder pattern applied to ListCollectionView (29452afe)
- Add IDisposable to DataGridCollectionView class declaration
- Add _collectionChangedForwarder field (WeakCollectionChangedForwarder?)
- Replace anonymous lambda subscription with forwarder in constructor
- Add Dispose() for eager cleanup
- Add WeakCollectionChangedForwarder nested class with self-unsubscribe on GC
- All Critical (P0) issues now fully resolved
- Update performance_memory_leak.md: 31/39 fixed (79.5%), Critical 7/7
- Add WeakCollectionChangedForwarder nested class: source holds strong ref to
forwarder, forwarder holds WeakReference<ListCollectionView> — prevents the
source collection from rooting the view
- Self-unsubscribes on next event after view is GC'd; no lingering delegate
- Keep IDisposable.Dispose() for eager cleanup when ItemsSource changes in ListView
- ListView: track _ownsCollectionView flag and call Dispose() on old view only
when we created it (not user-provided IListCollectionView)
- Remove OnDetachedFromVisualTree disposal to avoid breaking reattach scenarios
(tab switching, panel rebuilds, etc.) — WeakReference handles lifetime safely
- Update performance_memory_leak.md: mark 1.1 as fixed, progress 30/39 (76.9%)
- Always stop, unsubscribe, and null out old _delayTimer before creating new instance
- Prevents event handler accumulation when MinimumPopulateDelay changes
- Unify handling between Mentions and AbstractAutoComplete
- Fixes issue where timer event handlers would accumulate on rapid property changes
- StartActiveAnimation: dispose old CTS before creating new instance
- StopActiveAnimation: dispose CTS and set to null
- BuildActiveAnimation: dispose CTS before rebuilding animation
- Prevents WaitHandle and unmanaged resources from leaking during repeated animation start/stop cycles
- ColorSpectrum: convert CreateBitmapsAndColorMap to async Task with try-catch
- ColorSlider: convert UpdateBackground to async Task with IsAttachedToVisualTree check
- DataGrid: convert CopyToClipboard to async Task with exception handling
- SelectableTextBlock: convert Copy to async Task with IsAttachedToVisualTree check
- Keep original void methods for backward compatibility (fire-and-forget pattern)
- Add graceful exception handling to prevent app crashes
- Verify control is attached before updating UI after async operations
- Add _loadingTokens list to track all pending CTS instances
- Add CTS to list when async load starts
- Remove CTS from list and dispose in finally block
- Add cleanup logic in OnDetachedFromVisualTree to cancel and dispose all pending CTS
- Ensures all async operations are properly cleaned up when control is detached
- Prevents resource leaks and ensures no callbacks on detached controls
- Applied to both TreeView and CascaderView
- Move PropertyChanged subscription from constructor to OnAttachedToVisualTree
- Add PropertyChanged unsubscription in OnDetachedFromVisualTree
- Ensure proper lifecycle management when Watermark is reattached to visual tree
- Prevent memory leaks from glyph event handlers
Also update performance_memory_leak.md:
- Mark 5.9 (Watermark glyph.PropertyChanged lambda) as fixed
- Add fix timestamp and implementation details
- Replace anonymous lambda with named method HandleShowTimerTick()
- Call StopTimer() at the beginning of StartShowTimer() to clean up old timer
- Use ValueTuple to safely extract control reference from timer Tag
- Prevent multiple parallel timers when mouse moves quickly
Also update performance_memory_leak.md:
- Mark 5.6 (ToolTip service global event subscription) as fixed
- Add fix timestamp and implementation details
- Add Dispose() call in HandleCleanupMarqueeAnimation() to release unmanaged resources
- Set CancellationTokenSource to null after disposal
- Ensure complete lifecycle management of CancellationTokenSource
Also update performance_memory_leak.md:
- Mark 5.4 (MarqueeLabel animation cleanup) as fixed
- Add fix timestamp and implementation details
- Remove 8 private event handler delegate fields (_alphaInputValueChangedHandler, etc.)
- Add 8 private methods to replace delegate fields (HandleAlphaInputValueChanged, etc.)
- Update OnApplyTemplate to use method references instead of delegate fields
- Avoid allocating new delegate objects on each OnApplyTemplate call
- Improve code clarity by using private methods for lambdas that don't capture closure variables
Also update performance_memory_leak.md:
- Mark 5.3 (CompositeDisposable) as fixed
- Update 3.7 fix description to reflect the actual implementation using private methods
- Add fix timestamp and details
Move SelectionChanged event subscription from constructor to lifecycle hooks:
- Remove subscription from constructor
- Add subscription in OnAttachedToVisualTree()
- Add unsubscription in OnDetachedFromVisualTree()
This ensures proper cleanup when the control is detached from the visual tree,
following best practices for event management and preventing potential reference cycles.
File: src/AtomUI.Controls/Segmented/AbstractSegmented.cs
- Removed: SelectionChanged subscription from constructor
- Added: OnAttachedToVisualTree() override with subscription
- Added: OnDetachedFromVisualTree() override with unsubscription
Fixes issue 5.1 from performance_memory_leak.md analysis.
- Add CancellationToken parameter to ResetAsync() for cancellable operations
- Add OnAttachedToVisualTree to create CancellationTokenSource when control is attached
- Update OnDetachedFromVisualTree to cancel and dispose CancellationTokenSource when control is detached
- Add cancellation checks in CancelAllUploadTaskAsync() to respect cancellation requests
Fixes issue #4.8: async methods now support proper cancellation, allowing clean shutdown of pending upload operations when the control is destroyed or navigation occurs.
Fixes the issue where the event handler was being subscribed multiple times when the control was re-attached to the visual tree. By moving the subscription to the constructor (where it happens only once) and the unsubscription to OnDetachedFromVisualTree, we ensure the handler is properly managed throughout the control's lifetime.