How can I bind a property inside Path.Data
to a TemplateBinding
? I noticed that in this following example, the properties SegmentColor
and StrokeThickness
are set and updated correctly, but not the property TargetPoint
. Further testing seems to confirm the issue seems to be related to the property being nested in an element of Path.Data
. The following code tries to simplify the context which I am facing while creating the template for a custom control.
C#:
public class TestProgressBar : ProgressBar
{
public Brush SegmentColor
{
get { return (Brush)GetValue(SegmentColorProperty); }
set { SetValue(SegmentColorProperty, value); }
}
public double StrokeThickness
{
get { return (double)GetValue(StrokeThicknessProperty); }
set { SetValue(StrokeThicknessProperty, value); }
}
public Point TargetPoint
{
get { return (Point)GetValue(TargetPointProperty); }
set { SetValue(TargetPointProperty, value); }
}
public static readonly DependencyProperty StrokeThicknessProperty =
DependencyProperty.Register(nameof(StrokeThickness), typeof(double), typeof(TestProgressBar), new PropertyMetadata());
public static readonly DependencyProperty SegmentColorProperty =
DependencyProperty.Register(nameof(SegmentColor), typeof(Brush), typeof(TestProgressBar), new PropertyMetadata(new SolidColorBrush(Colors.Red)));
public static readonly DependencyProperty TargetPointProperty =
DependencyProperty.Register(nameof(TargetPoint), typeof(Point), typeof(TestProgressBar), new PropertyMetadata());
}
Xaml:
<c:TestProgressBar StrokeThickness="15"
TargetPoint="100,0">
<c:TestProgressBar.Style>
<Style TargetType="{x:Type c:TestProgressBar}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type c:TestProgressBar}">
<Grid>
<Path
Stroke="{TemplateBinding SegmentColor}"
StrokeThickness="{TemplateBinding StrokeThickness}"
Width="100" Height="100">
<Path.Data>
<PathGeometry>
<PathFigure>
<LineSegment Point="{TemplateBinding TargetPoint}"/>
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</c:TestProgressBar.Style>
</c:TestProgressBar>
It seems that using TemplateBindings within the Path.Data causes the issue. Replacing it with a TemplatedParent Binding fixes the issue:
<LineSegment Point="{Binding TargetPoint, RelativeSource={RelativeSource TemplatedParent}}"/>
I can't quite explain why this is, though. In my original code, I am using readonly dependency properties, so the issue can't be linked to TwoWay binding problems (as I've hard can be the case with TemplateBinding).
I know that Binding using TemplatedParent is runtime-evaluated, as opposed to compile-time for TemplateBinding, so perhaps something along those lines fixes the binding.