Overview
This article explains how to display text such as error messages or logs in WPF so that it remains non-editable while still allowing selection and copying.
Although TextBlock is suitable for display scenarios, it is not designed for partial text selection and copy operations in the same way as TextBox.
For this requirement, a practical approach is to use a read-only TextBox and adjust its appearance so it behaves like a display control.
Prerequisites / Environment
- Framework / Language: WPF / C# / XAML
- Target controls / features:
TextBlock,TextBox - Architecture: Applicable to both MVVM and code-behind implementations
- Intended use cases: Error messages, logs, and detail text display
- Verification environment: .NET 10 / Windows 11
The tables in this article were measured in the environment above.
Each caption states how its table was measured.
The following points were confirmed in that environment:
TextBlockexposes no API for selecting text.- A
TextBoxwithIsReadOnlyset still allows text selection. - Selection still works after applying the settings that make it look like a
TextBlock. - Clearing
IsTabStopleaves the control focusable.
Problem
In screens that display error messages or detailed information, the content often needs to remain non-editable while still being easy to copy.
A dedicated copy button is one possible solution, but many real-world cases require copying only a part of the displayed text.
This creates a need for a UI element that behaves as read-only display text while still supporting text selection and copy operations.
Cause / Background
TextBlock is a lightweight control intended for display-only text rendering and works well for static labels or descriptive text.
However, standard TextBlock usage is not well suited to workflows where users need to select and copy part of the rendered text.
TextBox, by contrast, is designed as an input control, but setting IsReadOnly="True" disables editing while preserving built-in text selection and copy behavior.
In addition, the background, border, and caret display can be adjusted so the control visually resembles a TextBlock.
For display scenarios, this makes it possible to treat a TextBox as a practical replacement for TextBlock.
The table below records, for each display-only candidate, whether the text can be selected and how it takes focus.
| control | SelectAll() selects | Focusable | IsTabStop |
|---|---|---|---|
| TextBlock | no selection API | False | True |
| TextBox IsReadOnly=True | selectable text | True | True |
| + borderless, transparent | selectable text | True | True |
| + IsTabStop=False | selectable text | True | False |
Measured on .NET 10 / Windows 11 with the same string given to each candidate. SelectAll() selects is the content read back from SelectedText after calling SelectAll().
TextBlock reports Focusable as False. Beyond lacking a selection API, it does not take focus at all.
Switching to a TextBox makes the text selectable, and removing the border and background does not change that. Appearance and behavior are independent here.
As the last row shows, setting IsTabStop to False leaves Focusable at True.
The control drops out of the Tab cycle while Focusable stays True and the selection API keeps working — which is the combination to use for a display-only look that still allows selection.
Solution
When display-only text also needs to be selectable, replace TextBlock with TextBox and apply a small set of visual and behavioral settings.
The key settings are as follows.
IsReadOnly="True"
Prevents editing while allowing selection and copyingBackground="Transparent"
Makes the background transparentBorderThickness="0"
Removes the borderPadding="0"
Removes the inner padding so the text sits where aTextBlockwould place itTextWrapping="Wrap"
Wraps long text across multiple lines
With this configuration, the control keeps the selection and copy behavior of TextBox while appearing close to TextBlock in common display layouts.
Implementation
The following XAML shows the minimal setup for displaying an error message as non-editable but still selectable text.
The control is styled so it can be used as a replacement for TextBlock in situations where copy support is required.
<TextBox
Text="{Binding ErrorMessage}"
IsReadOnly="True"
Background="Transparent"
BorderThickness="0"
Padding="0"
TextWrapping="Wrap" />
With this configuration, the displayed text cannot be modified, but users can still select any required part and copy it.
TextBlock (top) and by a read-only TextBox configured as described above (bottom). In the lower one, only the exception type name is selected. Because the background and border are removed, the unselected appearance is nearly identical to TextBlock.Because the appearance is also close to TextBlock, existing display-only text can often be replaced with TextBox without changing the surrounding layout significantly.
For long content, a vertical scroll bar can be added.
The following example shows that extended configuration.
<TextBox
Text="{Binding ErrorMessage}"
IsReadOnly="True"
Background="Transparent"
BorderThickness="0"
Padding="0"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
VerticalScrollBarVisibility="Auto" shows a scroll bar when the text exceeds the available display area. AcceptsReturn is not needed for text that already contains line breaks: it only decides whether the Enter key inserts one. A read-only TextBox showed three lines of text as three lines with AcceptsReturn set to False or True.
| case | measured |
|---|---|
| IsReadOnlyCaretVisible default | False |
| IsReadOnly, AcceptsReturn=False | LineCount 3, height 201 |
| IsReadOnly, AcceptsReturn=True | LineCount 3, height 201 |
Measured on .NET 10 / Windows 11 by reading the default of IsReadOnlyCaretVisible and showing line1 to line3 in a read-only TextBox.
Notes
TextBoxretains input-control characteristics, so default styling may introduce padding or focus visuals that differ fromTextBlock- A read-only
TextBoxdoes not show a caret by default:IsReadOnlyCaretVisibledefaults toFalse, soIsReadOnly="True"alone is enough. Set it toTrueonly when a visible caret is wanted, for example for keyboard selection - If strict visual consistency is required, additional properties such as
Padding,Focusable, or a shared style definition may also need adjustment
Alternatives / Comparison
| Method | Advantages | Disadvantages | Suitable cases |
|---|---|---|---|
Use TextBlock as-is |
Lightweight and appropriate for display-only text | Not well suited to partial selection and copying in standard use | Simple labels or static text |
Use a read-only TextBox |
Supports selection and copying and can be treated as a TextBlock replacement |
Requires appearance adjustments | Error messages, logs, and shareable detail text |
| Add a dedicated copy button | Enables one-click full-text copy | Not suitable when only part of the text needs to be copied | Full-copy scenarios such as IDs or predefined messages |
Summary
When WPF text must remain non-editable while still supporting selection and copying, using a read-only TextBox in place of TextBlock is an effective solution.
IsReadOnly="True" prevents editing, and since IsReadOnlyCaretVisible defaults to False, no caret appears to make the control look editable.
By also removing the border and background, the control can be used in the same kinds of display scenarios as TextBlock while preserving copy functionality.
This configuration is a suitable default pattern for any screen that displays text which users may need to reference and partially copy.
- TextBox (WPF Standard Control Demo App): measures that
IsReadOnlyignores typing but still allows selecting and copying