Preserve behavior visual lifecycle on virtualized containers - #360
Merged
Merged
Conversation
wieslawsoltes
marked this pull request as ready for review
July 14, 2026 22:18
This was referenced Aug 21, 2026
This was referenced Aug 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Keeps template-created behaviors operational when Avalonia replaces a
BehaviorCollectionon a control that is already attached to the visual tree. This fixesContextDragBehavioron virtualizedListBoxItemcontainers after scrolling/recycling.Reproduction analysis
The attached reproduction uses a
BehaviorCollectionTemplatein aListBoxItemstyle with Avalonia 11.3.13. Initially realized containers work, but newly visible items after scrolling do not start a drag.The failure is caused by collection replacement on an already-attached item container:
Interaction.BehaviorsProperty.BehaviorCollection.Detach()calls each behavior's normal detach hook, but it does not sendOnDetachedFromVisualTree.AttachedToVisualTreeevent is guaranteed for a recycled container that remains in the tree.ContextDragBehaviorBaseinstalls/removes pointer handlers in those visual-tree hooks.Avalonia 12 currently realizes fresh containers in the equivalent headless scenario, so scrolling alone does not force that older recycling path. The lifecycle defect remains reproducible on current master by replacing the template-created collection on an attached, newly visible item—the exact state transition performed by the older virtualizer.
Changes
Interaction.Behaviorsowner is currently attached to a visual tree.BehaviorCollectionTemplateinside a style instead of sharing a statefulBehaviorCollection.Tests
Core lifecycle regression
A new interactivity test shows a window, replaces a button's behavior collection while the button remains attached, and verifies:
Virtualized ContextDrag regression
A headless test mirrors the issue's 100-item virtualized
ListBoxand style-basedBehaviorCollectionTemplate, scrolls to a newly visible item, replaces its template collection while attached, and verifies:ContextDragBehaviorBasevisual lifecycle is balanced;Validation:
dotnet test tests/Xaml.Behaviors.Interactivity.UnitTests/Xaml.Behaviors.Interactivity.UnitTests.csproj --no-restoredotnet test tests/Xaml.Behaviors.Interactions.UnitTests/Xaml.Behaviors.Interactions.UnitTests.csproj --no-restoreCloses #336