How to Reuse Storyboard Using VisualStateManager in Silverlight 5

This question was asked before, but in most cases no more than 2 years ago and is often specific to WPF. The answer may still be the same, but here it goes. I am trying to create a triangular (arrow) button that changes color and grows in size when the mouse is over it. It works for me on one button. But now I need buttons with an arrow pointing in different directions. I want to use as much code as possible. Without using a custom button control, I couldn't think of a way to fully use the same style, so I'm trying to just reuse the mouse over the animation, making it a resource. When I refer to the Storyboard as a StaticResource in the VisualStateManager of my button template, it causes my button to completely disappear. Why is this not working?

<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:System="clr-namespace:System;assembly=mscorlib" mc:Ignorable="d" x:Class="SilverlightTest.MainPage" Width="640" Height="480"> <UserControl.Resources> <Storyboard x:Key="ArrowMouseOver"> <DoubleAnimation Duration="0:0:0.165" To="1.25" Storyboard.TargetProperty="(UiElement.RenderTransform).(ScaleTransform.ScaleX)" Storyboard.TargetName="polygon"/> <DoubleAnimation Duration="0:0:0.165" To="1.25" Storyboard.TargetProperty="(UiElement.RenderTransform).(ScaleTransform.ScaleY)" Storyboard.TargetName="polygon"/> <ColorAnimation Duration="0:0:0.165" To="#FF9BD6FF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/> <ColorAnimation Duration="0:0:0.165" To="#FF70ACDF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/> <ColorAnimation Duration="0:0:0.165" To="#FF7DAEFF" Storyboard.TargetProperty="(Shape.Stroke).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/> <ColorAnimation Duration="0:0:0.165" To="#FF2B5CB4" Storyboard.TargetProperty="(Shape.Stroke).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/> </Storyboard> <Style x:Key="LeftArrow" TargetType="Button"> <Setter Property="Cursor" Value="Hand"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Grid x:Name="grdRoot" RenderTransformOrigin="0.5,0.5"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualStateGroup.Transitions> <VisualTransition From="MouseOver" GeneratedDuration="0:0:0.165"/> </VisualStateGroup.Transitions> <VisualState x:Name="Normal"/> <VisualState x:Name="MouseOver" Storyboard="{StaticResource ArrowMouseOver}"> </VisualState> <VisualState x:Name="Pressed"/> <VisualState x:Name="Disabled"/> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Polygon x:Name="polygon" Grid.Row="0" Margin="1" StrokeThickness="{TemplateBinding BorderThickness}" HorizontalAlignment="Center" RenderTransformOrigin="0.5,0.5"> <Polygon.Points> <Point X="10"/> <Point X="0" Y="5" /> <Point Y="10" X="10" /> </Polygon.Points> <Polygon.RenderTransform> <ScaleTransform /> </Polygon.RenderTransform> <Polygon.Fill> <LinearGradientBrush EndPoint="0.5,0" StartPoint="0.5,1"> <GradientStop Color="#FFA9A9A9"/> <GradientStop Color="#FFD3D3D3" Offset="1"/> </LinearGradientBrush> </Polygon.Fill> <Polygon.Stroke> <LinearGradientBrush EndPoint="0.5,0" StartPoint="0.5,1"> <GradientStop Color="#FF696969"/> <GradientStop Color="#FF939393" Offset="1"/> </LinearGradientBrush> </Polygon.Stroke> </Polygon> <ContentPresenter Grid.Row="1" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </UserControl.Resources> <Grid x:Name="LayoutRoot" Background="White"> <Button Style="{StaticResource LeftArrow}" HorizontalAlignment="Left" VerticalAlignment="Top"> </Button> </Grid> 

+4
source share
2 answers

It looks like you should introduce your own Button class. I would do it like this:

 <my:GlowingArrowButton ArrowDirection="Left"/> 

And your generic.xaml:

 <Style TargetType="my:GlowingArrowButton"> <Setter Property="Cursor" Value="Hand"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="my:GlowingArrowButton"> <Grid x:Name="grdRoot" RenderTransformOrigin="0.5,0.5"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualStateGroup.Transitions> <VisualTransition From="MouseOver" GeneratedDuration="0:0:0.165"/> </VisualStateGroup.Transitions> <VisualState x:Name="Normal"/> <VisualState x:Name="MouseOver" <Storyboard> <DoubleAnimation Duration="0:0:0.165" To="1.25" Storyboard.TargetProperty="(UiElement.RenderTransform).(ScaleTransform.ScaleX)" Storyboard.TargetName="polygon"/> <DoubleAnimation Duration="0:0:0.165" To="1.25" Storyboard.TargetProperty="(UiElement.RenderTransform).(ScaleTransform.ScaleY)" Storyboard.TargetName="polygon"/> <ColorAnimation Duration="0:0:0.165" To="#FF9BD6FF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/> <ColorAnimation Duration="0:0:0.165" To="#FF70ACDF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/> <ColorAnimation Duration="0:0:0.165" To="#FF7DAEFF" Storyboard.TargetProperty="(Shape.Stroke).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/> <ColorAnimation Duration="0:0:0.165" To="#FF2B5CB4" Storyboard.TargetProperty="(Shape.Stroke).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/> </Storyboard> </VisualState> <VisualState x:Name="Pressed"/> <VisualState x:Name="Disabled"/> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <LayoutTransformer LayoutTransform="{Binding Path=ArrowDirection, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource RotationTranslator_ToBeImplemented}}" Grid.Row="0" HorizontalAlignment="Center"> <Polygon x:Name="polygon" Margin="1" StrokeThickness="{TemplateBinding BorderThickness}" RenderTransformOrigin="0.5,0.5"> <Polygon.Points> <Point X="10"/> <Point X="0" Y="5" /> <Point Y="10" X="10" /> </Polygon.Points> <Polygon.RenderTransform> <ScaleTransform /> </Polygon.RenderTransform> <Polygon.Fill> <LinearGradientBrush EndPoint="0.5,0" StartPoint="0.5,1"> <GradientStop Color="#FFA9A9A9"/> <GradientStop Color="#FFD3D3D3" Offset="1"/> </LinearGradientBrush> </Polygon.Fill> <Polygon.Stroke> <LinearGradientBrush EndPoint="0.5,0" StartPoint="0.5,1"> <GradientStop Color="#FF696969"/> <GradientStop Color="#FF939393" Offset="1"/> </LinearGradientBrush> </Polygon.Stroke> </Polygon> </LayoutTransformer> <ContentPresenter Grid.Row="1" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> 

And the code:

 public class GlowingArrowButton : ButtonBase { public GlowingArrowButton() { DefaultStyleKey = typeof (GlowingArrowButton); } public ArrowDirection ArrowDirection { get { return (ArrowDirection) GetValue( ArrowDirectionProperty ); } set { SetValue( ArrowDirectionProperty, value ); } } public static readonly DependencyProperty ArrowDirectionProperty = DependencyProperty.Register( "ArrowDirection", typeof( ArrowDirection ), typeof( GlowingArrowButton ), new PropertyMetadata( default( ArrowDirection ) ) ); } public enum ArrowDirection { Left, Up, Right, Down } 

[Edit] Written but not verified:

 public class RotationTranslator : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var arrowDirection = (ArrowDirection) value; switch (arrowDirection) { case ArrowDirection.Left: return new RotateTransform{ Angle = 0 }; case ArrowDirection.Up: return new RotateTransform { Angle = 90 }; case ArrowDirection.Right: return new RotateTransform { Angle = 180 }; case ArrowDirection.Down: return new RotateTransform { Angle = -90 }; } throw new InvalidOperationException(); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture){throw new NotSupportedException();} } 
+1
source

Storyboard requires DynamicResource markup DynamicResource and Silverlight does not support dynamic resources. "Strewth.

0
source

All Articles