Question

I am creating a control template for a checkbox, all is going well but I would like to use a gradient that is bound to the Foreground color.

Theoretically this should work, but it's coming out white.

<LinearGradientBrush x:Key="Shine" StartPoint="0,0" EndPoint="1,1">
    <GradientStopCollection>
        <GradientStop Offset="0" Color="{TemplateBinding Property=Foreground, Converter={StaticResource Color}}"/>
        <GradientStop Offset="0.5" Color="White"/>
        <GradientStop Offset="1" Color="{TemplateBinding Property=Foreground, Converter={StaticResource Color}}"/>
    </GradientStopCollection>
</LinearGradientBrush>

The ColorConverter code is

Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.Convert
    Dim S As SolidColorBrush = value
    Return S.Color
End Function

Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
    Return New SolidColorBrush(value)
End Function

I'm guessing I've missed something, but can't figure it out.

**Here's the complete resource dictionary:

<ResourceDictionary>
        <local:Reducer x:Key="Reducer"/>
        <local:StrokeConverter x:Key="Stroke"/>
        <local:VisibilityConverter x:Key="Visible"/>
        <local:ColorConverter x:Key="Color"/>
        <LinearGradientBrush x:Key="Green" StartPoint="0,0" EndPoint="1,1">
            <GradientStopCollection>
                <GradientStop Offset="0" Color="Green"/>
                <GradientStop Offset="0.5" Color="White"/>
                <GradientStop Offset="1" Color="Green"/>
            </GradientStopCollection>
        </LinearGradientBrush>
        <ControlTemplate x:Key="Chk" TargetType="CheckBox">
            <ControlTemplate.Resources>
                <LinearGradientBrush x:Key="Shine" StartPoint="0,0" EndPoint="1,1">
                    <GradientStopCollection>
                        <GradientStop Offset="0" Color="{TemplateBinding Property=Foreground}"/>
                        <GradientStop Offset="0.5" Color="White"/>
                        <GradientStop Offset="1" Color="{TemplateBinding Property=Foreground, Converter={StaticResource Color}}"/>
                    </GradientStopCollection>
                </LinearGradientBrush>
            </ControlTemplate.Resources>
            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{Binding RelativeSource={RelativeSource Mode=Self}, Path=ActualHeight, Converter={StaticResource Stroke}, ConverterParameter=10}"
                    Height="{TemplateBinding Height}" Width="{TemplateBinding Height}">
                <Grid Visibility="{TemplateBinding Converter={StaticResource Visible}, Property=IsChecked}" >
                    <Line Stroke="{StaticResource Shine}" StrokeThickness="{Binding RelativeSource={RelativeSource AncestorType=Grid},Path=ActualHeight,Converter={StaticResource Stroke}, ConverterParameter=6}" StrokeStartLineCap="Round" StrokeEndLineCap="Round"
                        X1="{Binding RelativeSource={RelativeSource AncestorType=Grid},Path=ActualHeight,Converter={StaticResource Reducer}, ConverterParameter=.15}"
                        X2="{Binding RelativeSource={RelativeSource AncestorType=Grid},Path=ActualHeight,Converter={StaticResource Reducer}, ConverterParameter=.35}"
                        Y1="{Binding RelativeSource={RelativeSource AncestorType=Grid},Path=ActualHeight,Converter={StaticResource Reducer}, ConverterParameter=.6}"
                        Y2="{Binding RelativeSource={RelativeSource AncestorType=Grid},Path=ActualHeight,Converter={StaticResource Reducer}, ConverterParameter=.85}"
                        />
                    <Line Stroke="{StaticResource Shine}" StrokeThickness="{Binding RelativeSource={RelativeSource AncestorType=Grid},Path=ActualHeight,Converter={StaticResource Stroke},ConverterParameter=6}" StrokeStartLineCap="Round" StrokeEndLineCap="Round"
                        X1="{Binding RelativeSource={RelativeSource AncestorType=Grid},Path=ActualHeight, Converter={StaticResource Reducer}, ConverterParameter=.35}"
                        X2="{Binding RelativeSource={RelativeSource AncestorType=Grid},Path=ActualHeight, Converter={StaticResource Reducer}, ConverterParameter=.85}"
                        Y1="{Binding RelativeSource={RelativeSource AncestorType=Grid},Path=ActualHeight,Converter={StaticResource Reducer}, ConverterParameter=.85}"
                        Y2="{Binding RelativeSource={RelativeSource AncestorType=Grid},Path=ActualHeight,Converter={StaticResource Reducer}, ConverterParameter=.15}"
                        />
                </Grid>
            </Border>
        </ControlTemplate>
    </ResourceDictionary>

And The Converters:

Public Class Reducer
Implements IValueConverter

Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.Convert
    Return value * parameter
End Function

Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
    Return value
End Function
End Class

Public Class StrokeConverter
Implements IValueConverter

Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.Convert
    Return value / parameter
End Function

Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
    Return value
End Function
End Class

Public Class VisibilityConverter
Implements IValueConverter

Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.Convert
    Dim V As Visibility = Visibility.Visible
    If value = False Then V = Visibility.Collapsed
    Return V
End Function

Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
    Return CType(value, Visibility) = Visibility.Visible
End Function
End Class

Public Class ColorConverter
Implements IValueConverter

Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.Convert
    Dim S As SolidColorBrush = value
    Return S.Color
End Function

Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
    Return New SolidColorBrush(value)
End Function
End Class
Was it helpful?

Solution

Your binding needs to be modified slightly:

<LinearGradientBrush x:Key="Shine" StartPoint="0,0" EndPoint="1,1">
  <GradientStopCollection>
    <GradientStop Offset="0" Color="{Binding Foreground, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource Color}}"/>
    <GradientStop Offset="0.5" Color="White"/>
    <GradientStop Offset="1" Color="{Binding Foreground, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource Color}}"/>
  </GradientStopCollection>
</LinearGradientBrush>

At first glance, it seems reasonable that a TemplateBinding is what you need, but you actually have to bind to a property of the TemplatedParent to achieve the result you want here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top