Skip to main content
Home Forums Silverlight Design Designing with Silverlight TemplateBinding of GradientStop Color
1 replies. Latest Post by agaac on November 15, 2009.
(0)
agaac
Member
20 points
10 Posts
11-06-2009 10:15 PM |
Hi,
I have a templated MyButton control that uses gradients inside to achieve various effects. For simplicity, let's say the whole control template is just a circle with a gradient (by default, Blue -> Transparent). The MouseOver state animates the gradient to a different color (Grey -> Transparent), which returns back to the original gradient (Blue -> Transparent) in Normal state.
What I want to achieve is: I want to give the user the control over the gradient color (Blue). I don't want the user to mess up with the entire gradient, just let them define this single color. Let's say the user wants to set it to Red, and I want all transitions and effects to still work correctly.
1) Since Background property is a Brush, I defined an extra dependency property in my class, called Glow, of type Color:
public class MyButton : Button { public Color Glow { get { return (Color) GetValue(GlowProperty); } set { SetValue(GlowProperty, value); } } public static readonly DependencyProperty GlowProperty = DependencyProperty.Register("Glow", typeof(Color), typeof(MyButton), new PropertyMetadata(Color.FromArgb(0xff, 0x00, 0x00, 0x88))); public MyButton() { this.DefaultStyleKey = typeof(MyButton); } }
2) Now, in theory, I should be able to use this value in my template:
<Style TargetType="local:MyButton"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="local:MyButton"> <Grid x:Name="LayoutRoot" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"> <Storyboard> <!-- Return to original Glow color --> <ColorAnimation Storyboard.TargetName="Glow" Storyboard.TargetProperty="Shape.Fill.(GradientBrush.GradientStops)[0].Color" To="{TemplateBinding Glow}" Duration="0:0:0.2"> </ColorAnimation> </Storyboard> </VisualState> <VisualState x:Name="MouseOver"> <Storyboard> <!-- Temporarily change gradient to different color --> <ColorAnimation Storyboard.TargetName="Glow" Storyboard.TargetProperty="Shape.Fill.(GradientBrush.GradientStops)[0].Color" To="#00888888" Duration="0:0:0.2"> </ColorAnimation> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Ellipse Stretch="Fill"> <Ellipse.Fill> <LinearGradientBrush StartPoint="0.5,1" EndPoint="0.5,0"> <LinearGradientBrush.GradientStops> <GradientStop Color="#00FFFFFF" Offset="0"/> <GradientStop Color="{TemplateBinding Glow}" Offset="1"/> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Ellipse.Fill> </Ellipse> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"> </ContentPresenter> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
But it doesn't work.. no error, just does nothing. I can change the Glow color to Red in the constructor, in OnApplyTemplate.. no result.
I heard binding to GradientStop is just not supported in SL (and it works in WPF). Anyone has any idea why it's not supported?
Anyone has any idea for a workaround?
I could simply set the gradient color to Glow in OnApplyTemplate.. but then I will have to also hardcode the behavior for the visual states and set up colors from code there as well.. which makes using templates pointless here if I have to hardcode colors.
A solution with giving the user access to the whole gradient is not good either - the transparency is used in combination with other template layers to create a very specific effect (not shown in the example). Setting the gradient to arbitrary values will destroy the whole effect.
Another solution I could think of is splitting the Ellipse to 2 layers: solid 1 color background (of type SolidColorBrush, bindable to a property set by user), and a White -> Transparent gradient on top of that. This will however make the template a bit complex (I use a number of gradients like these, splitting everything into 2 layers will make the XAML "heavy"). So I was thinking, maybe anyone has a better solution?
Thanks in advance
Agata
11-15-2009 10:06 AM |
As I figured out, this kind of binding is not supported by Silverlight, so I had to manually "bind" it in code :(
The explanation why, is here: http://blogs.msdn.com/nickkramer/archive/2006/08/18/705116.aspx