3

I'm new to WPF and I am struggling to find the solution to what I'm trying to do as I'm still a little uncertain as to whether I'm doing this correctly.

I have the following style defined for a button

<Style x:Key="ToolBarButtonStyle" TargetType="{x:Type Button}"> <Setter Property="Margin" Value="5" /> <Setter Property="BorderBrush" Value="White" /> <Setter Property="Background" Value="{DynamicResource CompanyBlue}" /> <Setter Property="Foreground" Value="White" /> <Setter Property="FontWeight" Value="Bold" /> <Setter Property="FontSize" Value="20" /> <Setter Property="Width" Value="100" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Border x:Name="ButtonBorder" BorderThickness="5" CornerRadius="5" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" Width="{TemplateBinding Width}"> <ContentPresenter Margin="10" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Border> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Button.Background"> <Setter.Value> <LinearGradientBrush StartPoint="0,-0.2" EndPoint="0,1.2"> <LinearGradientBrush.GradientStops> <GradientStop Color="White" Offset="0" /> <GradientStop Color="{ORIGINAL-COLOR}" Offset="0.5" /> <GradientStop Color="White" Offset="1" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Setter.Value> </Setter> </Trigger> </Style.Triggers> </Style> 

In the XAML, where I have put the placeholder {ORIGINAL-COLOR}, I essentially want this to be the value that is used previously set with {TemplateBinding Background} for the control template of the style.

I've seen suggestions that I should use {Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background} but this is not working.

Thanks in advance for any help.

8
  • In what way is it not working? What's the message/error or does it fail silently. Make sure you check the output window, because that's where WPF dumps a lot of debug information. Commented Mar 3, 2013 at 15:21
  • 1
    You can't bind Color with Background property since return type of Background is Brush and not Color. Commented Mar 3, 2013 at 15:22
  • The error I get is as follows: Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Background.Color; DataItem=null; target element is 'GradientStop' (HashCode=19346574); target property is 'Color' (type 'Color') Commented Mar 3, 2013 at 15:29
  • is ORIGINAL-COLOR static or dynamic? Commented Mar 3, 2013 at 15:31
  • ORIGINAL-COLOR is a placeholder for whatever should be there. That error I was from using {Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background.Color} Commented Mar 3, 2013 at 15:36

3 Answers 3

2

I believe the problem is that LinearGradientBrush is not a FrameworkElement and doesn't belong to layout tree. Only FrameworkElements have DataContext property and in consequence can make use of bindings. What you're trying to do is to set up a Binding on GradientStop.

Your trigger should look like this:

 <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Button.Background" Value="{TemplateBinding Background, Converter={StaticResource myConverter}}"> </Setter> </Trigger> 

And myConverter is a custom converter class that will take value of Background and return a complete LinearGradientBrush instance created from input brush. I'll assume you know how to write converters. Remember it needs to be added to resources.

More or less something like this:

 class BrushToGradient : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var brush = (Brush)value; var gradient = new LinearGradientBrush(); //Make it manually gradient.GradientStops.Add(...); //... return gradient; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } 
Sign up to request clarification or add additional context in comments.

1 Comment

I got this solution to work with a couple of tweaks. In the trigger, the TemplateBinding shortcut cannot be used, and also, because of my actual control template I also needed to set the TargetName attribute on the Setter: <Setter Property="Background" TargetName="ButtonBorder" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background, Converter={StaticResource ToolBarSolidToLinearGradient}}" />
0

You can't bind Color with Background property since return type of Background is Brush and not Color.

Bind with Color property of Brush. Since background is binded to resource CompanyBlue so use that binding in your trigger as well -

<GradientStop Color="{Binding Color, Source={StaticResource CompanyBlue}}" Offset="0.5" /> 

Comments

0

Try it like this

<GradientStop Color="White" Offset="0" /> <GradientStop Color="{DynamicResource CompanyBlue}" Offset="0.5" /> <GradientStop Color="White" Offset="1" /> 

I hope this will help.

1 Comment

That would help if I wanted it to always be that value, but it can be overwritten when using the style (which is why I set the background to {TemplateBinding Background}) and would want that overwritten value to be used in this scenario.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.