I have created a custom circular progress bar control which inherits from the original WPF ProgressBar
. In its default style/template I want to define a storyboard for the indeterminate animation. However, I can’t seem to find a way to animate the Value
property of my control. Here’s the default style.
<Style x:Key="{x:Type control:CircularProgressIndicator}" TargetType="{x:Type control:CircularProgressIndicator}" BasedOn="{StaticResource {x:Type ProgressBar}}">
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type control:CircularProgressIndicator}">
<Grid>
<Path x:Name="PART_Path"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Stroke="{TemplateBinding Foreground}"
StrokeThickness="{TemplateBinding StrokeThickness}">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure x:Name="PART_Figure">
<PathFigure.Segments>
<PathSegmentCollection>
<ArcSegment x:Name="PART_ArcSegment" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Determinate" />
<VisualState x:Name="Indeterminate">
<Storyboard>
<!-- this throws a binding error: "Cannot find governing FrameworkElement or FrameworkContentElemnt for target element." -->
<DoubleAnimation Storyboard.Target="{Binding RelativeSource={RelativeSource TemplatedParent}}"
Storyboard.TargetProperty="Value"
From="0" To="100" RepeatBehavior="Forever" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="VerticalContentAlignment" Value="Center" />
</Style>
There’s obviously all kinds of code in CircularProgressIndicator
that manipulates the Path
element based on the Value
property but that shouldn’t be relevant here. The problem is how generally to animate properties of the templated control itself from a storyboard. Obviously, there’s no named element that I could pass to Storyboard.TargetName
. I already tried some trickery with binding proxies but so far nothing worked.
I did find several entries for this problem here on SO already but they either had no answers or they solved it from outside of the template (i.e. you would either have to duplicate the relevant code at every use site or use a Behavior
to encapsulate that) which IMHO defeats the purpose of having a template in the first place…
There must be some better way, mustn’t there?