Text on a ProgressBar in WPF
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
WPF's ProgressBar control is good at showing progress visually, but it does not have a built-in text property for overlay content. In real applications you often want both: the bar itself and text such as 42%, Downloading, or 3 of 8 files. The normal solution is to compose controls rather than trying to force ProgressBar to render text on its own.
Why Overlaying Works Well in WPF
WPF layout makes it easy to stack controls in the same visual area. A Grid is the simplest approach because child elements share the same cell unless you place them elsewhere. That means you can put a ProgressBar in the background and a centered TextBlock on top.
This keeps responsibilities clear:
- '
ProgressBarshows progress value' - '
TextBlockshows readable status' - bindings keep both in sync
That is usually better than editing the control template unless you need a fully reusable custom style.
A Basic XAML Overlay
Here is the simplest version:
This is enough for fixed text, but most real screens need dynamic values. WPF binding makes that straightforward.
Binding the Text to the Same Value
A clean pattern is to expose progress state from a view model and bind both controls to it.
Bind that model in XAML:
This is a solid default because the text formatting stays in one place and the view remains simple.
Showing Richer Status Than a Percentage
Many applications need more than a percentage. You may want to display file counts, transfer speed, or a short status string. In that case, do not derive everything from the progress bar value. Store a dedicated status property.
Then bind the TextBlock to Status instead of ProgressText. The bar and the text can still update together, but they no longer pretend to represent the same kind of data.
When to Use a Control Template
If one screen needs overlaid text, the Grid approach is enough. If the same pattern appears throughout the application, a custom style or user control is better because it removes duplicate XAML.
A reusable user control can expose:
- '
Value' - '
Minimum' - '
Maximum' - '
OverlayText'
That gives you a single component with a clean API while still relying on ordinary composition internally.
Visual Concerns
Text readability can degrade when the filled portion of the bar uses a dark color. A few practical fixes help:
- use a bold font weight
- keep the bar height tall enough for readable text
- choose a foreground color with strong contrast
- reduce visual clutter around the progress area
If the bar fill color changes dynamically, consider switching the text color based on theme or background contrast.
Indeterminate Progress
For indeterminate operations, the bar does not represent an exact numeric value, so percentage text becomes misleading. In that case, overlay status text such as Loading... or Connecting... and set IsIndeterminate="True".
This is a good reminder that the text is not just decoration. It communicates the meaning of the progress indicator.
Common Pitfalls
A common mistake is putting text inside a ProgressBar and expecting the control to render it. ProgressBar is not a content control, so that approach does not work.
Another issue is hardcoding the overlay text while the progress value changes. That leaves the user looking at stale information.
Be careful with alignment and margins. If the text is not centered in the same container as the bar, resizing can make the overlay drift.
Finally, avoid overcomplicating the solution with a custom template unless the project genuinely needs reuse or custom theming. For one screen, a Grid with bindings is easier to maintain.
Summary
- WPF
ProgressBardoes not natively render overlay text. - The simplest solution is to stack a
TextBlockon top of it in aGrid. - Bind the bar value and the overlay text to the same view model when they represent the same state.
- Use a dedicated status property when the text is not just a percentage.
- Prefer composition first and move to a reusable control only when repetition justifies it.
- For indeterminate progress, use descriptive status text instead of fake numeric percentages.
Related reading
- Text on the left side of checkbox in WPF?
- The case for or against .NET the beast
- The cast to value type 'Int32' failed because the materialized value is null
- The character breaks passwords that are stored in the web.config
- The current .NET SDK does not support targeting .NET 6.0. Either target .NET 5.0 or lower, or use a version of the .NET SDK that supports .NET 6.0
- The current .NET SDK does not support targeting .NET Core 2.1. Either target .NET Core 2.0 or lower, or use a .NET SDK that supports .NET Core 2.1
- The current SynchronizationContext may not be used as a TaskScheduler
- The difference between Task.Factory.FromAsync and BeginX/EndX?

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.