ProgressBarControl
Progress indicator for tasks — determinate with a percentage, or indeterminate with a pulsing animation.

Overview#
ProgressBarControl shows how far along a task is. In determinate mode you set Value against
MaxValue and the bar fills proportionally, optionally printing the percentage. In
indeterminate mode the bar runs a pulsing block back and forth — the right choice when you know
work is happening but not how much is left.
Values are clamped for you: Value is held within [0, MaxValue], and MaxValue has a floor of
0.01, so a stray assignment can't produce a divide-by-zero or a bar past full. The control
stretches horizontally by default.
It is a display control — no focus, no keyboard or mouse handling. For a measured quantity that isn't task progress (CPU load, disk usage) prefer BarGraphControl; for a value the user can change, use SliderControl.
Quick Start#
var progress = Controls.ProgressBar()
.WithHeader("Downloading")
.WithPercentage(0)
.ShowPercentage()
.Build();
window.AddControl(progress);
// Advance it — assigning Value repaints on its own
progress.Value = 45;
Builder API#
Create a builder with Controls.ProgressBar().
Value#
.WithValue(double value) // Current value
.WithMaxValue(double maxValue) // Full-scale value (default 100)
.WithPercentage(double percentage) // Convenience: value on a 0–100 scale
Indeterminate mode#
.Indeterminate(bool indeterminate = true) // Pulsing animation instead of a fill
.WithAnimationInterval(int milliseconds) // Pulse tick rate (default 100)
.WithPulseWidth(int width) // Width of the moving block (default 5)
Header and readout#
.WithHeader(string header)
.ShowHeader(bool show = true)
.ShowPercentage(bool show = true)
Size and layout#
.WithBarWidth(int width) // Fixed bar width
.Stretch() // Fill the available width
.WithWidth(int width)
.WithAlignment(HorizontalAlignment alignment)
.WithVerticalAlignment(VerticalAlignment alignment)
.WithMargin(int left, int top, int right, int bottom)
.WithMargin(Margin margin)
.StickyTop()
.StickyBottom()
.Visible(bool visible)
.WithName(string name)
.WithTag(object tag)
Colors#
.WithFilledColor(Color color)
.WithUnfilledColor(Color color)
.WithColors(Color filled, Color unfilled)
.WithPercentageColor(Color color)
.WithBackgroundColor(Color color)
.WithColorRole(ColorRole role, ThemeMode? mode = null)
.Outline(bool outline = true)
Properties#
| Property | Type | Default | Description |
|---|---|---|---|
Value |
double |
0 |
Current progress, clamped to [0, MaxValue] |
MaxValue |
double |
100.0 |
Full-scale value; floored at 0.01 |
IsIndeterminate |
bool |
false |
Pulsing mode; setting it starts/stops the animation timer |
AnimationInterval |
int |
100 |
Pulse tick interval in milliseconds |
PulseWidth |
int |
5 |
Width of the pulsing block |
BarWidth |
int? |
null |
Fixed bar width; stretches when null |
ShowPercentage |
bool |
— | Whether the percentage readout is drawn |
ShowHeader |
bool |
— | Whether the header is drawn |
Header |
string? |
null |
Header text above the bar |
FilledColor |
Color? |
null |
Filled portion; theme color when null |
UnfilledColor |
Color? |
null |
Empty track; theme color when null |
PercentageColor |
Color? |
null |
Percentage text color |
BackgroundColor |
Color? |
null |
Control background; inherits when null |
ColorRole |
ColorRole |
Default |
Semantic color role |
ColorRoleMode |
ThemeMode? |
null |
Optional theme mode override |
Outline |
bool |
false |
Outline styling |
The control sets HorizontalAlignment.Stretch in its constructor, so it fills its container unless
you give it a BarWidth or a different alignment.
Events#
None. ProgressBarControl implements INotifyPropertyChanged via BaseControl, so its properties
can be data-bound — see Data Binding.
Keyboard and mouse support#
None — this is a display-only control.
Examples#
Determinate progress from a background task#
var progress = Controls.ProgressBar()
.WithName("copyProgress")
.WithHeader("Copying files")
.WithMaxValue(totalFiles)
.ShowPercentage()
.Stretch()
.Build();
window.AddControl(progress);
// From a worker — assigning Value only invalidates, so this is safe off the UI thread
for (int i = 0; i < totalFiles; i++)
{
await CopyFileAsync(files[i], ct);
progress.Value = i + 1;
}
Adding or removing controls from a background thread is not safe — route that through
windowSystem.EnqueueOnUIThread(...). See Threading & Async.
Indeterminate work#
Use this when there is no meaningful percentage — a network handshake, a query with unknown length.
var spinner = Controls.ProgressBar()
.WithHeader("Connecting…")
.Indeterminate()
.WithPulseWidth(8)
.WithAnimationInterval(80)
.Build();
// Switch to determinate once the total is known
spinner.IsIndeterminate = false;
spinner.MaxValue = totalBytes;
spinner.Value = 0;
Semantic coloring#
var bar = Controls.ProgressBar()
.WithHeader("Disk usage")
.WithPercentage(91)
.WithColorRole(ColorRole.Danger)
.ShowPercentage()
.Build();
Fixed width, no header#
var inline = Controls.ProgressBar()
.WithBarWidth(24)
.WithPercentage(60)
.ShowHeader(false)
.ShowPercentage()
.WithFilledColor(Color.Cyan1)
.WithUnfilledColor(Color.Grey23)
.Build();
Non-percentage scale#
var download = Controls.ProgressBar()
.WithHeader("Download")
.WithMaxValue(totalBytes) // e.g. 5_242_880
.WithValue(receivedBytes)
.ShowPercentage() // still displayed as a percentage of MaxValue
.Build();
Best Practices#
- Use indeterminate mode when you genuinely don't know the total. A determinate bar that jumps from 0 to 100 is worse than an honest pulse.
- Turn the animation off when the work ends. Set
IsIndeterminate = false— the pulse runs a timer, and leaving it on burns frames for no reason. - Set
MaxValueto the real total (bytes, files, steps) instead of pre-computing a percentage; the readout is still a percentage, and the code stays clearer. - Prefer
WithColorRoleto hardcoded colors so the bar tracks the active theme. - Don't use it for measured quantities. A CPU meter is not progress — BarGraphControl is the right control there.
- Assign
Valueand stop. The setter clamps and invalidates; callingInvalidateyourself is redundant. - For a modal "please wait" flow,
Dialogs.RunWithProgressAsyncalready wraps a progress dialog — see Dialogs.
See Also#
- BarGraphControl — a measured value against a maximum
- SparklineControl — a value series over time
- SliderControl — an interactive value
- SpinnerControl — a compact activity indicator
- Dialogs —
RunWithProgressAsyncfor modal progress - Themes — color roles