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.

Phil
  • 42,255
  • 9
  • 100
  • 100
Adam Goss
  • 1,017
  • 3
  • 14
  • 22
  • 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. – pbalaga Mar 03 '13 at 15:21
  • 1
    You can't bind `Color` with `Background` property since return type of `Background` is `Brush` and not `Color`. – Rohit Vats Mar 03 '13 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') – Adam Goss Mar 03 '13 at 15:29
  • is ORIGINAL-COLOR static or dynamic? – yo chauhan Mar 03 '13 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} – Adam Goss Mar 03 '13 at 15:36
  • I just have copied and pasted the above code . Its Trigger is not working at all. – yo chauhan Mar 03 '13 at 15:43
  • If I replace {ORIGINAL-COLOR} with a hardcoded value such as 'White' then it would work as expected, but I'm trying to have it be the same color as the original background, rather then hard-coding the value. – Adam Goss Mar 03 '13 at 15:45
  • yes thats what i was asking that is original background static or dynamic . if it is static then you can just replace it harcoded like White – yo chauhan Mar 03 '13 at 15:47

3 Answers3

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();
    }
}
pbalaga
  • 2,018
  • 1
  • 21
  • 33
  • 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: `` – Adam Goss Mar 03 '13 at 16:35
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" />
Rohit Vats
  • 79,502
  • 12
  • 161
  • 185
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.

yo chauhan
  • 12,079
  • 4
  • 39
  • 58
  • 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. – Adam Goss Mar 03 '13 at 16:02