Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ static void UpdateInlines(
{
var textBlockInlines = textBlock.Inlines;
textBlockInlines.Clear();
var textHighlighters = textBlock.TextHighlighters;
Comment thread
SubhikshaSf4851 marked this conversation as resolved.
textHighlighters.Clear();

// Have to implement a measure here, otherwise inline.ContentStart and ContentEnd will be null, when used in RecalculatePositions
textBlock.Measure(new global::Windows.Foundation.Size(double.MaxValue, double.MaxValue));
Expand Down Expand Up @@ -97,7 +99,7 @@ static void UpdateInlines(
};

run.Foreground = textColor?.ToPlatform();
textBlock.TextHighlighters.Add(textHighlighter);
textHighlighters.Add(textHighlighter);
}

currentTextIndex += runTextLength;
Expand Down
51 changes: 51 additions & 0 deletions src/Controls/tests/DeviceTests/Elements/FormattedStringTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,56 @@ public async Task NativeFormattedStringContainsSpan()

Assert.Equal("HELLOWORLD", actual);
}

// Covers https://github.com/dotnet/maui/issues/36519
// Updating Label.FormattedText must clear any highlighter/background-color state applied
// by the previous FormattedText. On Windows specifically, the native TextBlock's
// TextHighlighters collection was never cleared, so stale highlighter ranges (from
// BackgroundColor/TextColor spans) survived and bled onto the new text, leaking
// TextHighlighter instances. This test verifies the rendered output on all platforms,
// with an additional native-collection check on Windows.
[Fact]
public async Task UpdatingFormattedTextClearsPreviousHighlights()
{
var label = new Label
{
WidthRequest = 200,
HeightRequest = 50,
FontSize = 16,
FormattedText = new FormattedString
{
Spans =
{
new Span { Text = "Highlighted", BackgroundColor = Colors.Red },
new Span { Text = " text", TextColor = Colors.Blue },
}
},
};

await InvokeOnMainThreadAsync(async () =>
{
var handler = CreateHandler<LabelHandler>(label);

#if WINDOWS
// Sanity check: highlighters were created for the initial FormattedText
Assert.NotEmpty(handler.PlatformView.TextHighlighters);
#endif
await handler.PlatformView.AssertContainsColor(Colors.Red, MauiContext);

// Update to a FormattedString with no highlighted spans at all
label.FormattedText = new FormattedString
{
Spans =
{
new Span { Text = "Plain text with no highlights" },
}
};

#if WINDOWS
Assert.Empty(handler.PlatformView.TextHighlighters);
#endif
await handler.PlatformView.AssertDoesNotContainColor(Colors.Red, MauiContext);
});
}
}
}
Loading