Controls

TextBlock

TextBlock is the framework's lightweight read-only text element. Use it to render labels, captions, status text, headings, and bound string values without the editing behavior of TextBox.

Quick start

TextBlock renders plain text. Its main inputs are Text, Foreground, TextWrapping, and the inherited font properties from FrameworkElement.

Minimal text

<TextBlock Text="Ready." />

Styled label

<TextBlock Text="Build completed"
           Foreground="#AEE7FF"
           FontSize="18"
           FontWeight="Bold" />

Wrapped paragraph

<Border Width="320" Padding="12" Background="#16212D">
  <TextBlock Text="This paragraph wraps to the available width of its container."
             TextWrapping="Wrap" />
</Border>

Default recommendation: prefer TextBlock for display-only text. If users need to edit text, switch to TextBox or RichTextBox.

When to use TextBlock

Good fits

Static labels, data-bound text, headers, helper text, diagnostics, counters, and compact text inside templates.

Not a fit

Editable text, inline rich formatting, selectable text, or scenarios that depend on WPF's Inlines, trimming, or brush-based text APIs.

  • TextBlock is a FrameworkElement, not a Control.
  • It does not expose a content model. The rendered value comes from Text.
  • It is intentionally lightweight and optimized for common read-only text scenarios.

Text and line breaking

The Text property is a string dependency property. You can set it directly, bind it, or assign it with property-element syntax.

Direct string assignment

<TextBlock Text="Server: online" />

Binding to a view model property

<TextBlock Text="{Binding StatusMessage}" />

Property-element syntax

<TextBlock>
  <TextBlock.Text>
    Bound or explicit text still ends up in the same Text property.
  </TextBlock.Text>
</TextBlock>

Explicit new lines

\r, \n, and \r\n split the text into separate logical lines regardless of wrapping mode.

Single-line default

TextWrapping defaults to NoWrap, so a single logical line measures at its intrinsic width.

Token-based wrapping

Wrapped layout breaks at whitespace when possible and breaks long tokens into smaller pieces only when they cannot fit.

Multi-line text from explicit line breaks

<TextBlock Text="Line one
Line two
Line three" />

Long token wrapping

<Border Width="180" Padding="8" Background="#131C27">
  <TextBlock Text="DiagnosticIdentifier_ThisIsAVeryLongTokenWithoutSpaces"
             TextWrapping="Wrap" />
</Border>

Layout behavior

TextBlock measures to the size required by its laid out text. The available width only matters when wrapping is enabled or when the text already contains explicit line breaks.

TextWrapping="NoWrap"

Single-line text measures to its intrinsic width and one line height. This is the fast path and is reused aggressively when only the available size changes.

TextWrapping="Wrap"

The available width becomes a layout input. Narrower widths can increase the number of lines and therefore the measured height.

  • Empty or null Text measures to 0 x 0.
  • Desired height grows as the line count grows.
  • Increasing FontSize increases the measured height.
  • Normal layout properties such as Width, Height, Margin, MinWidth, and MaxWidth still apply because TextBlock inherits from FrameworkElement.

Wrapping depends on container width

<StackPanel>
  <Border Width="320" Padding="10" Background="#1A2431">
    <TextBlock Text="The wider container keeps this on fewer lines."
               TextWrapping="Wrap" />
  </Border>

  <Border Width="180" Padding="10" Margin="0,8,0,0" Background="#1A2431">
    <TextBlock Text="The narrower container produces more wrapped lines."
               TextWrapping="Wrap" />
  </Border>
</StackPanel>

Rendering and appearance

TextBlock renders each produced line with the resolved typography and Foreground color. Element Opacity is applied during drawing.

Foreground

The text color. The default is white. In this framework it is a Color value, not a brush object.

Font properties

FontFamily, FontSize, FontWeight, and FontStyle are inherited from ancestor elements unless overridden locally.

No text background

TextBlock only renders text. If you need chrome behind it, place it inside a Border, Grid, or another container.

Simple emphasis

<TextBlock Text="Critical"
           Foreground="#FF8C82"
           FontWeight="Bold"
           FontSize="20" />

Dim secondary copy

<TextBlock Text="Last synced 2 minutes ago"
           Foreground="#8BA1B8"
           Opacity="0.9" />

Typography inheritance

Because the font properties are inherited dependency properties, a parent container can define typography once and child TextBlock elements pick it up automatically.

<StackPanel FontFamily="Segoe UI"
            FontSize="16"
            FontWeight="Normal">
  <TextBlock Text="Section title" FontWeight="Bold" FontSize="22" />
  <TextBlock Text="Shared family and base size come from the parent." />
  <TextBlock Text="This one also inherits them." Foreground="#9FC2D9" />
</StackPanel>

Default values: FontSize defaults to 12, FontWeight defaults to Normal, and FontStyle defaults to Normal.

Property reference

Primary properties

Text: the string to render. Empty text produces no visible output and measures to zero.

Foreground: a Color used for drawing text. Default: white.

TextWrapping: NoWrap, Wrap, or WrapWithOverflow. Default: NoWrap.

Inherited layout and font properties

FontFamily, FontSize, FontWeight, FontStyle: control typography.

Margin, Width, Height, MinWidth, MaxWidth, and alignment properties: participate in normal layout.

Opacity: multiplies the rendered text color during drawing.

Current implementation note: WrapWithOverflow goes through the same wrapped layout path as Wrap today. Do not rely on distinct WPF overflow semantics here unless the framework documents that separately in a future release.

Patterns and examples

Dialog header and body copy

<StackPanel Width="420">
  <TextBlock Text="Delete saved capture?"
             FontSize="24"
             FontWeight="Bold"
             Margin="0,0,0,8" />
  <TextBlock Text="This action permanently removes the local file and cannot be undone."
             TextWrapping="Wrap"
             Foreground="#AFC3D6" />
</StackPanel>

Value label pair

<StackPanel>
  <TextBlock Text="FPS" Foreground="#7F96AB" />
  <TextBlock Text="{Binding FramesPerSecond}"
             FontSize="28"
             FontWeight="Bold" />
</StackPanel>

Status line inside chrome

<Border Background="#172331"
        BorderBrush="#36506B"
        BorderThickness="1"
        Padding="10,8">
  <TextBlock Text="{Binding ConnectionSummary}"
             Foreground="#D6EEFF" />
</Border>

Template content

<Style x:Key="HeadlineLabelStyle" TargetType="{x:Type Label}">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Label}">
        <Border Background="#111A24" Padding="12,8">
          <TextBlock Text="{TemplateBinding Content}"
                     FontSize="18"
                     FontWeight="Bold" />
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Dense diagnostics column

<StackPanel FontFamily="Consolas" FontSize="14">
  <TextBlock Text="Frame 000128" />
  <TextBlock Text="Draw calls: 54" />
  <TextBlock Text="Dirty regions: 3" />
  <TextBlock Text="Renderer: retained" />
</StackPanel>

Performance notes

TextBlock includes layout caching and an optimized intrinsic measurement path for common display text cases.

  • Single-line NoWrap text avoids the more expensive wrapped layout builder.
  • Wrapped single-line text can still reuse measurement work when the available width stays above the intrinsic line width.
  • Changing Text, TextWrapping, FontSize, FontFamily, FontWeight, or FontStyle invalidates the cached layout.
  • If you have many read-only labels, TextBlock is the intended primitive.

Practical guidance: use NoWrap for short labels and counters when possible. Enable wrapping when readability matters more than the extra layout work.

Differences from WPF to keep in mind

Foreground is a color, not a brush. Examples should use values that resolve to Color, such as #AEE7FF.

No inline rich text model. This control renders a plain string. If you need access-key parsing, use AccessText; if you need rich document content, use RichTextBox or DocumentViewer.

No WPF text trimming API is documented here. If text must fit, control that with layout, wrapping, or alternative UI patterns rather than assuming ellipsis behavior.