Changing the lineargradient offset colour of content template based on templatebinding background colour WPF

1.8k Views Asked by At

Ok so here's the problem. Am trying to figure out how to make this work:

Consider the following ControlTemplate for creating a Custom Button:

<ControlTemplate x:Key ="cButton" TargetType="{x:Type Button}">
      <!--Styles-->
      <Grid x:Name="bkg">
      <Grid.Background>
         <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
           <GradientStop Color="{TemplateBinding Background}" Offset="0.5"/><!-- Error! -->
           <GradientStop Color="White" Offset="1.0"/>
       </LinearGradientBrush>
      </Grid.Background>
      <ContentPresenter 
    TextBlock.FontSize="80" 
    HorizontalAlignment="Center" 
    VerticalAlignment="Center" 
    ContentSource="Content" />
      </Grid>
      <!--Triggers-->
      <ControlTemplate.Triggers>
         <Trigger Property="IsPressed" Value="True">
         <Setter TargetName="bkg" Property="Background" Value="White"/>
         </Trigger>
      </ControlTemplate.Triggers>
   </ControlTemplate>

This Control Template forms part of this script and as you can see I am trying to get the background colour from the button declaration outlined in the main grid.

<Grid>
<Grid.Resources>
   <ControlTemplate x:Key ="cButton" TargetType="{x:Type Button}">
      <!--Styles-->
      <Grid x:Name="bkg">
      <Grid.Background>
         <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
           <GradientStop Color="{TemplateBinding Background}" Offset="0.5"/><!-- Error! -->
           <GradientStop Color="White" Offset="1.0"/>
       </LinearGradientBrush>
      </Grid.Background>
      <ContentPresenter 
    TextBlock.FontSize="80" 
    HorizontalAlignment="Center" 
    VerticalAlignment="Center" 
    ContentSource="Content" />
      </Grid>
      <!--Triggers-->
      <ControlTemplate.Triggers>
         <Trigger Property="IsPressed" Value="True">
         <Setter TargetName="bkg" Property="Background" Value="White"/>
         </Trigger>
      </ControlTemplate.Triggers>
   </ControlTemplate>
  </Grid.Resources>
  <Grid.ColumnDefinitions>
   <ColumnDefinition Width="*"/>
    <ColumnDefinition Width="*"/>
  </Grid.ColumnDefinitions >
  <Button Name="btnIn" Grid.Column="0" Content="IN" Background="Green"  Foreground="White" Template="{StaticResource cButton}"/>
  <Button Name="btnOut" Grid.Column="1" Content="OUT" Background="Red" Foreground="White" Template="{StaticResource cButton}" />
  </Grid>

Ok now Main question is this one..

Question 1: Why is the line marked with an Error Comment in the ControlTemplate of the button NOT retrieving the background colour using the templatebinding? Had I used a solid colour it would have worked fine so I see no reason why it should not work in this manner. And please provide reason why this is happening.

The following are still a bit unclear and I don't know if they may be related to the problem, if someone can clear them out it would be great.

Question 2: What is the difference between these two TargetType values "Button" and "{x:Type Button}". I know that they are a typeof equivalent but is there any difference between the two? I read MSDN but the real difference is not that clear.

Question 3: When would I use x:Name and when would I use Name ? The difference again is unclear.

Question 4: What does x:Static do?

1

There are 1 best solutions below

5
On

I think that your template does not work correctly because Background property is a Brush (class). And you try bind it to Color (struct)

UPD You can use simple converter like this:

public class BrushToColorConverter: IValueConverter{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        SolidColorBrush b = value as SolidColorBrush;
        if (b != null)
        {
            return b.Color;
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Add it to resources:

<wpfApplication1:BrushToColorConverter x:Key="btcConv"/>

And modify your style:

 <Grid.Background>
                    <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                        <GradientStop Color="{Binding Path=Background, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource btcConv}}" Offset="0.5"/>
                        <GradientStop Color="White" Offset="1.0"/>
                    </LinearGradientBrush>
                </Grid.Background>

Or you can use binding like this (if you sure that Background is SolidColorBrush):

<GradientStop Color="{Binding Path=Background.Color, RelativeSource={RelativeSource TemplatedParent}}" Offset="0.5"/>