From 2688d791c828c1e7cffe8757b9f617f3645c4488 Mon Sep 17 00:00:00 2001 From: Quin Gillespie Date: Sat, 7 Mar 2026 12:10:57 -0700 Subject: [PATCH] Fix screen reader reading wrong line on blank lines (#7190) When navigating a TextBox or RichTextBox line-by-line with a screen reader (Narrator, NVDA), blank lines caused the next line's content to be announced instead of "blank", and that next line would then be announced again on the following navigation. Root cause: In TextRangeAdaptor.ExpandToEnclosingUnit(TextUnit.Line), blank lines produce a degenerate lineRange where Start == End (ContentLength == 0). The condition lineRange.Contains(_end) fails when _end has already advanced past the blank line, so snapEndPosition stays true and the expandEnd block runs, bleeding _end into the next non-blank line. The resulting range spans both the blank line and the next line, so GetText() returns the next line's content. Fix: add an additional guard clause for the degenerate case: if (lineRange.Contains(_end) || lineRange.Start.CompareTo(lineRange.End) == 0) When lineRange.Start == lineRange.End (blank line), snapEndPosition is set to false and _end is snapped to lineRange.End (same position), preventing expandEnd from running. GetText() returns "" and screen readers correctly announce "blank". Covers TextBox (TextBoxView.GetLineRange returns [offset, offset] for blank lines) and RichTextBox (TextDocumentView returns a degenerate segment for empty paragraphs). Fixes #7190 --- .../System/Windows/Controls/TextRangeAdaptor.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/TextRangeAdaptor.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/TextRangeAdaptor.cs index 86addb9d09c..c7a87170634 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/TextRangeAdaptor.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/TextRangeAdaptor.cs @@ -607,8 +607,11 @@ private void ExpandToEnclosingUnit(TextUnit unit, bool expandStart, bool expandE _start = lineRange.Start.CreatePointer(); } // If this line contains also end position, move it to the - // end of this line. - if (lineRange.Contains(_end)) + // end of this line. Also handle blank/empty lines where + // lineRange.Start == lineRange.End (ContentLength == 0): + // snap _end to the blank line boundary so expandEnd doesn't + // bleed into the next line. + if (lineRange.Contains(_end) || lineRange.Start.CompareTo(lineRange.End) == 0) { snapEndPosition = false; if (_end.CompareTo(lineRange.End) != 0)