Uses binding to re-evaluate the string when dependencies change.
Strings are commonly used where a Visual is expected because Visual defines an implicit conversion:
string -> Visual creates a TextBlock with that string.
Properties
Text : string? (bindable)
Wrap : bool (bindable)
When false (default), the control renders as a single row (height 1).
TextAlignment : TextAlignment (bindable)
Supported: Left, Center, Right, Justify.
Trimming : TextTrimming (bindable)
Supported: Clip, EndEllipsis, StartEllipsis.
Trimming is applied only in single-line rendering.
There are no events and no input handling.
Layout and rendering
Measurement model
TextBlock measures to a fixed size based on:
the text's cell width (not string length)
the wrap flag and available width
the available height (clamped)
Let:
text = Text ?? ""
naturalWidth = TerminalTextUtility.GetWidth(text)
width = min(constraints.MaxWidth, naturalWidth)
When Wrap is false or width == 0:
desired size is (width, 1) (height is clamped to 1)
When Wrap is true:
height is computed as the number of wrapped lines for the given width (at least 1)
desired height is clamped to constraints.MaxHeight
Notes:
The measured width does not attempt to "stretch to fill" when there is more horizontal space than the text requires.
Stretching is handled by layout via HorizontalAlignment = Align.Stretch if desired.
Rendering model
Render uses:
TerminalTextUtility to compute cell widths and safe slice boundaries
TextBlockStyle.ResolveTextStyle(theme) to determine the style applied to written glyph cells
If TextBlockStyle.FillBackground is enabled and a Background is set:
the control fills its entire Bounds rectangle with spaces using ResolveFillStyle(theme)
then renders text on top
If FillBackground is false:
background colors (when set) apply only to the glyph cells written by the text rendering operations
Single-line rendering (no wrap or height == 1)
Single-line rendering supports trimming:
Clip:
clip the text to Bounds.Width cells and write it
EndEllipsis / StartEllipsis:
if the text does not fit and Bounds.Width == 1, render only an ellipsis glyph (U+2026)
otherwise reserve 1 cell for the ellipsis and clip the remainder
Alignment is applied after trimming/clipping:
TextAlignment.Left: x = Bounds.X
TextAlignment.Center: centered
TextAlignment.Right: right aligned
Implementation details:
clipping is performed with TerminalTextUtility.TryGetIndexAtCell(...) so the control does not split multi-cell runes
or grapheme clusters incorrectly
start-ellipsis uses TerminalTextUtility.GetPreviousTextElementIndex(...) to find a safe suffix boundary from the end
Multi-line wrapping (Wrap == true and height > 1)
Wrapping logic is whitespace-based and "paragraph-like":
leading whitespace on each new line is skipped
the slice for a line is the largest prefix that fits within Bounds.Width cells
if the slice does not reach the end of the string, the algorithm attempts to wrap at the last whitespace within the
slice
newline characters are treated as whitespace, so explicit newlines naturally force breaks
after selecting a wrap slice, trailing whitespace is skipped for the next line start
In wrapped mode:
trimming (ellipsis) is not applied; each line is clipped to width
TextAlignment.Justify is supported for non-last lines only
Justification
When TextAlignment == TextAlignment.Justify and the current line is not the last line of the wrapped text:
the renderer attempts to distribute extra spaces between words so the line fills the entire width
Constraints and fallback:
the justification algorithm supports up to 32 words per line (uses stackalloc for performance)
if there are too many words, or if the base line already exceeds the width, the renderer falls back to normal clipped
writing (left aligned)
Styling
TextBlockStyle
TextBlockStyle provides optional overrides for:
Foreground : Color?
Background : Color?
TextStyle : TextStyle (decorations like bold/underline)
FillBackground : bool
Important default behavior:
TextBlockStyle.Default does not set any explicit colors, which means TextBlock commonly inherits from whatever the
buffer or parent visuals wrote before it. This is intentional and enables patterns like:
filling a row background in a parent, then rendering text that inherits that baseline
Tests
TextBlockRenderingTests validates:
end-ellipsis trimming renders U+2026 for small widths
start-ellipsis trimming renders U+2026 for small widths
center alignment works when horizontally stretched
background styling applies to text-only vs filled background depending on FillBackground
Future / v2 ideas
Optional explicit line break handling with preserved empty lines (current behavior treats whitespace uniformly).
Optional trimming behavior for wrapped mode (e.g., show ellipsis on the last visible line when height is constrained).
Optional hyphenation or more advanced line breaking (current behavior wraps at whitespace only).