Repository navigation
Release the TextBlock text layout when the control is detached - #22281
Merged
Gillibald merged 1 commit intoOct 5, 2026
Merged
Conversation
NuGet packagesThe packages for this pull request have been published (workflow run):
|
Gillibald
approved these changes
Sep 30, 2026
Gillibald
left a comment
Contributor
There was a problem hiding this comment.
LGTM
Thanks for the contribution
grokys
pushed a commit
to Evan260/Avalonia
that referenced
this pull request
Oct 7, 2026
MrJul
pushed a commit
that referenced
this pull request
Oct 9, 2026
3 of 4 tasks
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.
What does the pull request do?
TextBlockkeeps itsTextLayoutalive after it has been detached from the visual tree, whenever the layout was built while the measure was already invalid.What is the current behavior?
TextLayoutis only released fromOnMeasureInvalidated.InvalidateMeasureraises that override only while the measure is still valid, so once the measure has been invalidated the control holds its layout (and the native resources it owns) until the next measure pass.A render pass reads
TextBlock.TextLayout, which materializes the layout lazily. Reading it between an invalidation and the next measure pass therefore leaves the control holding a layout that nothing will release. If the control is then removed from the tree, the layout is never disposed.What is the updated/expected behavior with this PR?
The layout is released when the control leaves the visual tree, regardless of the state of its measure.
TextLayoutis materialized lazily, so a control that is attached again rebuilds it on the next measure or render pass.How was the solution implemented (if it's not obvious)?
OnDetachedFromVisualTreecalls the existingDisposeTextLayout, which is unconditional.Three tests were added:
Detaching_Should_Release_TextLayoutthe case that already passes today, kept so the two paths are visible side by side.Detaching_Should_Release_TextLayout_Built_While_Measure_Is_Invalidthe failing case. It is the only test inAvalonia.Controls.UnitTeststhat fails without the fix (1 of 3966).Reattaching_Should_Rebuild_TextLayouta regression guard for disposing on detach. It passes with and without the fix; it is there to catch a control left blank after being reattached.The tests observe the layout through a new
internal bool HasTextLayout, following the existinginternal bool HasComplexContent, rather than through reflection.Checklist
Breaking changes
None
Obsoletions / Deprecations
None
Fixed issues
None