4

I'm sure this has been solved before but I can't find a proper solution right know.. Probably I just don't know the terms I'm searching for.

Assuming I have this Custom Control Template

<Style x:Key="ColorPicker" TargetType="{x:Type local:ColorPicker}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:ColorPicker}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <Thumb Width="30" Height="30" Canvas.Left="0" Canvas.Top="0">
                        <Thumb.Style>
                            <Style TargetType="Thumb">
                                <Setter Property="Template">
                                    <Setter.Value>
                                        <ControlTemplate>
                                            <Ellipse Fill="{TemplateBinding SelectedColor}" Width="30" Height="30" Stroke="Black" StrokeThickness="1" />
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </Thumb.Style>
                    </Thumb>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

where SelectedColor is a Property of ColorPicker. In the sample above, template binding would look for SelectedColor in the template parent of type Thumb, however how can i get a binding to the second level template parent?

Xaser
  • 2,066
  • 2
  • 22
  • 45

1 Answers1

6
Fill="{Path=SelectedColor, RelativeSource={RelativeSource FindAncestor, AncestorType={local:ColorPicker}}}"

In your ColorPicker style, this will traverse up to the ColorPickers property and not the one on Thumb. I generally find this to be a far safer binding, and hardly ever use TemplateBinding. Been burned so many times in customcontrols using TemplateBinding!

Anyways full code :)

<Style x:Key="ColorPicker" TargetType="{x:Type local:ColorPicker}">
<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type local:ColorPicker}">
            <Border Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}">
                <Thumb Width="30" Height="30" Canvas.Left="0" Canvas.Top="0">
                    <Thumb.Style>
                        <Style TargetType="Thumb">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate>
                                        <Ellipse Fill="{Path=SelectedColor.Color, RelativeSource={RelativeSource FindAncestor, AncestorType={local:ColorPicker}}}" Width="30" Height="30" Stroke="Black" StrokeThickness="1" />
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </Thumb.Style>
                </Thumb>
            </Border>
        </ControlTemplate>
    </Setter.Value>
</Setter>

WPF Cheatsheet is a compact list of all types of bindings, very handy!

Cheers,

Stian

Stígandr
  • 2,874
  • 21
  • 36
  • Also I'd like to point out that TemplateBinding has certain advantages as well over normal binding. See [here](http://stackoverflow.com/questions/1131222/wpf-templatebinding-vs-relativesource-templatedparent) – Xaser Aug 25 '14 at 20:08
  • 1
    Thanks, I even tried that and the reason it didn't work was that I bound a SolidBrush to the Color property. should have been SelectedColor.Color. I'll mark this as the correct answer though and +1 for the cheatsheet – Xaser Aug 25 '14 at 20:30
  • 1
    @Xaser I updated the example there for correcting the binding. I tend to mess a bit with the same myself from time to time :) – Stígandr Aug 25 '14 at 20:45
  • thanks, its much cleaner now. though for this example, the proper type for `Ellipse.Fill` is a `Brush`, as opposed to a `GradientStop.Color` which has to be a `Color`. Just so nobody gets confused ;) – Xaser Aug 25 '14 at 21:37