0
votes

I've been trying (failing) to create a button template, to be shared between libraries. The template is (currently) basically a bordered circle inside a bordered circle. In order to make the inner border's size smaller than the outer, I use a Converter on the binding. I'd like to pass in a property of the TemplatedParent as a ConverterParameter but it just doesn't work, apparently by design. The bit that doesn't work is because I'm trying to bind a ConveterParameter to a TemplatedParent property.

Here's my Style def (in a ResourceDictionary):

<SolidColorBrush x:Key="MyBorderFillColour">Yellow</SolidColorBrush>
<SolidColorBrush x:Key="MyBorderEdgeColour">#ff652f00</SolidColorBrush>
<SolidColorBrush x:Key="MyGeneralFillColour">#ffffffbd</SolidColorBrush>
<s:Int32 x:Key="MyBorderThickness">10</s:Int32>

<l:RelativeSizeConverter x:Key="RelativeSizeConverter" />

<Style x:Key="MyButtonStyle" TargetType="Button">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid>
                    <Ellipse 
                        Fill="{StaticResource MyBorderFillColour}" 
                        StrokeThickness="2" 
                        Stroke="{StaticResource MyBorderEdgeColour}" 
                        Height="{TemplateBinding Height}" 
                        Width="{TemplateBinding Width}" />
                    <Ellipse StrokeThickness="2" 
                        Stroke="{StaticResource MyBorderEdgeColour}" 
                        Fill="{StaticResource MyGeneralFillColour}"
                        Height="{Binding Path=Height,
                            RelativeSource={RelativeSource TemplatedParent}, 
                            Converter={StaticResource RelativeSizeConverter},
                            ConverterParameter={StaticResource MyBorderThickness}}"
                        Width="{Binding Path=Width,
                            RelativeSource={RelativeSource TemplatedParent}, 
                            Converter={StaticResource RelativeSizeConverter},
                            ConverterParameter={TemplateBinding BorderThickness}}" />
                    <TextBlock 
                        Text="{TemplateBinding Content}" 
                        HorizontalAlignment="Center" 
                        VerticalAlignment="Center" 
                        Foreground="Black" 
                        FontFamily="Calibri"
                        FontWeight="Bold"
                        FontSize="17" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

The second Ellipse's Height works using a StaticResource, but Width doesn't work using the TemplateBinding approach. I've also tried

ConverterParameter={Binding Path=BorderThickness,RelativeSource={RelativeSource TemplatedParent}}

Any idea how to achieve my aim?!?

Thanks for any help,

2

2 Answers

0
votes

This does not work because in order to provide a binding expression for a value, the value must be a dependency property. ConverterParameter is not a dependency property so you cannot bind its value.

How about using a slightly less generic approach, where you create a few slightly more specific value converters. You can then use a 'dot' path, so that your Button is passed as the value to the converter, you can then access teh width, border width etc... directly.

  Width="{Binding Path=.,
                        RelativeSource={RelativeSource TemplatedParent}, 
                        Converter={StaticResource RelativeWidthWidthBorderSizeConverter}}"
0
votes

You don't need to do anything so fancy here; the layout system will handle it for you (using the Margin property and the stretching behavior of the Ellipse in a container):

    <Grid Height="{TemplateBinding Height}" Width="{TemplateBinding Width}">
        <Ellipse 
                    Fill="{StaticResource MyBorderFillColour}" 
                    StrokeThickness="2" 
                    Stroke="{StaticResource MyBorderEdgeColour}"/> 
        <Ellipse StrokeThickness="2" Margin="4"
                    Stroke="{StaticResource MyBorderEdgeColour}" 
                    Fill="{StaticResource MyGeneralFillColour}"/>
        <TextBlock 
                    Text="{TemplateBinding Content}" 
                    HorizontalAlignment="Center" 
                    VerticalAlignment="Center" 
                    Foreground="Black" 
                    FontFamily="Calibri"
                    FontWeight="Bold"
                    FontSize="17" />
    </Grid>

Note also that you should use a ContentPresenter for the Content instead of a TextBlock for more flexibility; this currently fails the Button contract if the user of the templated button supplies more complex Content.