Dependency property does not work within a geometry in a controltemplate

Go To StackoverFlow.com

0

I have a DepencencyProperty (a boolean) that works fine on an Ellipse, but not on an ArcSegment. Am I doing something that is not possible? Here's part of the xaml. Both the TemplateBindings of Origin and LargeArc do not work in the geometry. But the LargeArc DependencyProperty does work in the Ellipse, so my DependencyProperty seems to be set up correctly.

 <ControlTemplate TargetType="{x:Type nodes:TestCircle}">
     <Canvas Background="AliceBlue">
         <Ellipse Height="10" Width="10" Fill="Yellow" Visibility="{TemplateBinding LargeArc, Converter={StaticResource BoolToVisConverter}}"/>
         <Path Canvas.Left="0" Canvas.Top="0" Stroke="Black" StrokeThickness="3">
             <Path.Data>
                 <GeometryGroup>
                     <PathGeometry>
                         <PathFigure IsClosed="True" StartPoint="{TemplateBinding Origin}">
                             <LineSegment Point="150,100" />
                             <ArcSegment Point="140,150" IsLargeArc="{TemplateBinding LargeArc}" Size="50,50" SweepDirection="Clockwise"/>
                         </PathFigure>
                     </PathGeometry>
                 </GeometryGroup>
             </Path.Data>
         </Path>
     </Canvas>
 </ControlTemplate>

What I'm trying to build is a (sort of) pie-shaped usercontrol where the shape of the Pie is defined by DependencyProperties and the actual graphics used are in a template, so they can be replaced or customized. In other words: I would like the code-behind to be visual-free (which, I assume, is good separation).

SOLUTION--------------------------(I'm not allowed to answer my own questions yet)

I found the answer myself, and this can be useful for others encountering the same issue. This is why the TemplateBinding on the Geometry failed:

A TemplateBinding will only work when binding a DependencyProperty to another DependencyProperty.

Following article set me on the right track: http://blogs.msdn.com/b/liviuc/archive/2009/12/14/wpf-templatebinding-vs-relativesource-templatedparent.aspx

The ArcSegment properties are no DependencyProperties. Thus, the solution to the above problem is to replace

<ArcSegment Point="140,150" IsLargeArc="{TemplateBinding LargeArc}"

with

<ArcSegment Point="140,150" IsLargeArc="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=LargeArc}"

Colin, your working example where an 'ordinary' binding was used in the geometry set me on the right track. BTW, love the infographics and the construction of your UserControl in your blogpost. And, hey, that quick tip on code snippets, and especially on that DP attribute and the separation of those DPs into a partial class file is pure gold!

2012-04-03 21:28
by Erik Bongers


0

That should work. Whilst I cannot see an immediate issue, I just thought I would point out that I wrote an article which included a Silverlight implementation of a pie-piece shape:

Plotting Circular Relationship Graphs with Silverlight

The XAML for this shape is shown below:

<Style TargetType="local:NodeSegment">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="local:NodeSegment"> 
          <Path Stroke="{TemplateBinding Stroke}"
                StrokeThickness="{TemplateBinding StrokeThickness}"
                Fill="{TemplateBinding Background}"
                DataContext="{Binding ViewModel}"
                x:Name="segmentShape">
            <Path.Data>
              <PathGeometry>
                <PathFigure StartPoint="{Binding Path=S1}"
                            IsClosed="True">
                  <ArcSegment Point="{Binding Path=S2}"
                              SweepDirection="Counterclockwise"
                              IsLargeArc="{Binding Path=IsLargeArc}"
                              Size="{Binding Path=OuterSize}"/>
                  <LineSegment Point="{Binding Path=S3}"/>
                  <ArcSegment Point="{Binding Path=S4}"
                              SweepDirection="Clockwise"
                              IsLargeArc="{Binding Path=IsLargeArc}"
                              Size="{Binding Path=InnerSize}"/>
                </PathFigure>
              </PathGeometry>
            </Path.Data>
          </Path>                      
        </Canvas>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>
2012-04-03 21:41
by ColinE
Thank you for the reply - it's reassuring that I'm on the right track. I'll double check for bugs then. Ah...I see you use Binding inside the PathGeometry while using TemplateBinding at the Path level...I'll have a look at that possibility as well. I'm no WPF expert, but I guess the Bindings point to data in the DataContext, that is the ViewModel object - Erik Bongers 2012-04-03 21:49
The ordinary binding instead of TemplateBinding does it! See description of full solution above, in the question - Erik Bongers 2012-04-03 23:12