I have an MVVM-based WPF 4 application which uses a ProgressBar to show the percentage completion of a long-running operation.
<ProgressBar Name="ProgressBar"
IsIndeterminate="False"
Minimum="0"
Maximum="100"
Value="{Binding Path=ProgressPercentageComplete, Mode=OneWay}"
Visibility="Visible"/>
I am happy for the "pulsing" animation to occur while the progress bar is moving, but once it reaches 100% I'd like it to stop animating and just remain static at 100%.
I've tried setting IsIndeterminate="False"
but this doesn't help and I can see why after reading the MSDN Documentation:
When this property is true, the
ProgressBar animates a few bars moving
across the ProgressBar in a continuous
manner and ignores the Value property.
Is it possible to stop this animation? Either completely, or just at 100%.
Best Answer
I wrote a generalized solution for this using an attached property, allowing me to toggle the behavior on any
ProgressBar
simply through a direct property or style setter, like so:The code:
Basically, it adds a
ValueChanged
handler which adjusts the visibility of the animated element.A few notes:
I'm using
"PART_GlowRect"
to find the animated element, although someone called this a hack. I disagree: this element name is officially documented through TemplatePartAttribute, which you can see in ProgressBar's declaration. While it's true that this doesn't necessarily guarantee that the named element exists, the only reason it should be missing is if the animation feature isn't supported at all. If it is supported but uses a different element name than the one documented, I would consider that a bug, not an implementation detail.Since I'm pulling an element out of the template, it's also necessary to handle the
Loaded
event (which is raised when a template is applied) to wait for the template to become available before attempting to set initial visibility, and if necessary set it again when the template is replaced on the fly by a theme change.Rather than explicitly toggling
Visibility
betweenCollapsed
andVisible
, I'm using SetCurrentValue to set toCollapsed
, and InvalidateProperty to reset it.SetCurrentValue
applies a value that does not take priority over other value sources, andInvalidateProperty
re-evaluates the property without taking theSetCurrentValue
setting into consideration. This ensures that if there are existing styles or triggers which would affect the visibility under normal conditions (i.e. when it is not at 100%), it would reset to that behavior if the progress bar is reused (going from 100% back to 0%) rather than being hard-coded toVisible
.