So I have a Path object that is implemented as follows:
<Path x:Name="arrow" Data="M0,0L0.67,0 4,2.67 7.25,0 8,0 8,0.67 4,4 0,0.75z" Fill="Black" Height="4" RenderTransformOrigin="0.5,0.5" Stretch="None" Width="8">
<Path.RenderTransform>
<TransformGroup>
<RotateTransform Angle="0"/>
<TranslateTransform/>
</TransformGroup>
</Path.RenderTransform>
</Path>
With this Path I have the following animation attached that works perfectly.
WORKING:
<VisualStateGroup x:Name="ExpandStateGroup">
<VisualState x:Name="Expanded">
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" To="180" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)" Storyboard.TargetName="arrow"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Collapsed">
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)" Storyboard.TargetName="arrow"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
However when I add the color animations neither of the animations work. Also, the expand seems to happen instantaneously rather than expanding smoothly. The Collapse works fine though.
NOT WORKING:
<VisualStateGroup x:Name="ExpandStateGroup">
<VisualState x:Name="Expanded">
<Storyboard>
<ColorAnimation To="Red" Duration="0:0:0.2" Storyboard.TargetProperty="(Path.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="arrow" />
<DoubleAnimation Duration="0:0:0.2" To="180" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)" Storyboard.TargetName="arrow"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Collapsed">
<Storyboard>
<ColorAnimation To="Black" Duration="0:0:0.2" Storyboard.TargetProperty="(Path.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="arrow" />
<DoubleAnimation Duration="0:0:0.2" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)" Storyboard.TargetName="arrow"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
It has to do with the coloranimation because when I try to perform the color animation by itself it doesn't work.
This is a part of the Telerik RadExpander user control.
If any other information is needed please don't hesitate to ask.
NOTE 1:
If I set the Fill color in the path declaration to black and set the collapsed fill color to green the arrow will start out as green, but as soon as I expand it turns black and never changes color again.
Note 2: When the coloranimation is set the doubleanimation never works.
Related
I have a customized animated button with this style:
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ControlTemplate.Resources>
<Storyboard x:Key="MenuBtnMouseEnterSb">
<DoubleAnimation Storyboard.TargetProperty="ScaleX" Storyboard.TargetName="btnScaleTransform"
To="0.92"
Duration="0:0:0.1">
<DoubleAnimation.EasingFunction>
<ExponentialEase Exponent="2" EasingMode="EaseInOut"></ExponentialEase>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation Storyboard.TargetProperty="ScaleY" Storyboard.TargetName="btnScaleTransform"
To="0.92"
Duration="0:0:0.1">
<DoubleAnimation.EasingFunction>
<ExponentialEase Exponent="2" EasingMode="EaseInOut"></ExponentialEase>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
<Storyboard x:Key="MenuBtnMouseExitSb">
<DoubleAnimation Storyboard.TargetProperty="ScaleX" Storyboard.TargetName="btnScaleTransform"
To="1"
Duration="0:0:0.2">
<DoubleAnimation.EasingFunction>
<BounceEase Bounces="1" Bounciness="5"></BounceEase>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation Storyboard.TargetProperty="ScaleY" Storyboard.TargetName="btnScaleTransform"
To="1"
Duration="0:0:0.2">
<DoubleAnimation.EasingFunction>
<BounceEase Bounces="1" Bounciness="5" EasingMode="EaseInOut">
</BounceEase>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
<Storyboard x:Key="MenuBtnMouseClickSb" AutoReverse="True">
<DoubleAnimation Storyboard.TargetProperty="ScaleX" Storyboard.TargetName="btnScaleTransform"
To="0.75"
Duration="0:0:0.2"></DoubleAnimation>
<DoubleAnimation Storyboard.TargetProperty="ScaleY" Storyboard.TargetName="btnScaleTransform"
To="0.75"
Duration="0:0:0.2"></DoubleAnimation>
</Storyboard>
</ControlTemplate.Resources>
<Border x:Name="border" BorderBrush="Transparent" CornerRadius="10" Background="{TemplateBinding Background}" Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}" TextBlock.Foreground="{TemplateBinding Foreground}" Margin="{TemplateBinding Margin}" Padding="{TemplateBinding Padding}" RenderTransformOrigin="0.5, 0.5">
<ContentPresenter Margin="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RecognizesAccessKey="True" />
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1" x:Name="btnScaleTransform"></ScaleTransform>
</TransformGroup>
</Border.RenderTransform>
<Border.Triggers>
<EventTrigger RoutedEvent="Button.MouseEnter">
<BeginStoryboard Storyboard="{DynamicResource MenuBtnMouseEnterSb}" />
</EventTrigger>
<EventTrigger RoutedEvent="Button.MouseLeave">
<BeginStoryboard Storyboard="{DynamicResource MenuBtnMouseExitSb}" />
</EventTrigger>
<EventTrigger RoutedEvent="Button.PreviewMouseDown">
<BeginStoryboard Storyboard="{DynamicResource MenuBtnMouseClickSb}" />
</EventTrigger>
</Border.Triggers>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Basically, whenever mouse enters this button - button becomes smaller and when PreviewMouseDown event happens (when I press mouse button) it must become even more small. But what actually happens is that button returns to it's original size when I press a left button - i.e. MouseLeave event is fired and when I release left mouse button MouseEnter is fired again.
I added handlers for PreviewMouseDown and MouseLeave events and after PreviewMouseDown is handled - MouseLeave is handled immediately which I suppose is causing the MouseExit animation to run instead of MouseClick.
I've tested it again with Console.Writelines in each handler and it seems that MouseLeave handler is not called but animation still works as I described earlier.
I removed MouseLeave eventtrigger and now proper mousedown animation is running but it returns only to 0.92 scale (MouseEnter animation) and cannot return to original size when cursor is outside (that's what MouseLeave animation did).
The solution for my problem is simple: Use VisualStates instead of Triggers for such task.
I just copied my animations into VisualStates and they now work as I expected:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="ScaleX" Storyboard.TargetName="btnScaleTransform"
To="1"
Duration="0:0:0.2">
<DoubleAnimation.EasingFunction>
<BounceEase Bounces="1" Bounciness="5"></BounceEase>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation Storyboard.TargetProperty="ScaleY" Storyboard.TargetName="btnScaleTransform"
To="1"
Duration="0:0:0.2">
<DoubleAnimation.EasingFunction>
<BounceEase Bounces="1" Bounciness="5" EasingMode="EaseInOut">
</BounceEase>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="ScaleX" Storyboard.TargetName="btnScaleTransform"
To="0.92"
Duration="0:0:0.1">
<DoubleAnimation.EasingFunction>
<ExponentialEase Exponent="2" EasingMode="EaseInOut"></ExponentialEase>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation Storyboard.TargetProperty="ScaleY" Storyboard.TargetName="btnScaleTransform"
To="0.92"
Duration="0:0:0.1">
<DoubleAnimation.EasingFunction>
<ExponentialEase Exponent="2" EasingMode="EaseInOut"></ExponentialEase>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="ScaleX" Storyboard.TargetName="btnScaleTransform"
To="0.75"
Duration="0:0:0.2">
</DoubleAnimation>
<DoubleAnimation Storyboard.TargetProperty="ScaleY" Storyboard.TargetName="btnScaleTransform"
To="0.75"
Duration="0:0:0.2">
</DoubleAnimation>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
Although it is kind of weird how Trigger based animations work...
So I have a path setup like this
<Grid x:Name="arrowPanel">
<Path x:Name="arrow" Data="M0,4 H8 M4,4 V8Z" Stroke="Black" StrokeThickness="2" Height="8" RenderTransformOrigin="0.5,0.5" Stretch="None" Width="8">
<!--Not sure what to do here -->
</Path>
</Grid>
I have a storyboard setup like this
<VisualStateGroup x:Name="ExpandStateGroup">
<VisualState x:Name="Expanded">
<Storyboard>
<!-- Something to change the data to this 'M0,5 H10'(A minus sign)-->
</Storyboard>
</VisualState>
<VisualState x:Name="Collapsed">
<Storyboard>
<!-- Something to change the data back to it's original 'M0,5 H10 M5,5 V10Z' (A plus sign)-->
</Storyboard>
</VisualState>
</VisualStateGroup>
I do not know how to alter the data aspect of the path to make these transformations.
You could use an ObjectAnimationUsingKeyFrames to "animate" the Data property of the Path:
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0"
Storyboard.TargetName="arrow" Storyboard.TargetProperty="Data">
<DiscreteObjectKeyFrame>
<DiscreteObjectKeyFrame.Value>
<Geometry>M0,5 H10</Geometry>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
In order to get the results I was looking for I created two paths that occupied the same area. One with the plus sign and the other with the minus sign (The plus sign without the vertical path).
Object:
<Grid>
<Grid x:Name="plusSignPanel">
<!-- Minus -->
<Path Data="M0,4 H8" Stroke="Red" StrokeThickness="2" Height="8" RenderTransformOrigin="0.5,0.5" Stretch="None" Width="8"/>
<!-- Plus -->
<Path x:Name="plusSign" Data="M0,4 H8 M4,4 V8Z" Stroke="Black" StrokeThickness="2" Height="8" RenderTransformOrigin="0.5,0.5" Stretch="None" Width="8"/>
</Grid>
</Grid>
And then all I did was change the color from black to transparent using the coloranimation on the plus sign for expanded state and vice versa with the collapsed state:
Animation:
<VisualStateGroup x:Name="ExpandStateGroup">
<VisualState x:Name="Expanded">
<Storyboard>
<ColorAnimation Duration="0:0:0.1" Storyboard.TargetName="plusSign" Storyboard.TargetProperty="(Path.Stroke).(SolidColorBrush.Color)" To="Transparent"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Collapsed">
<Storyboard>
<ColorAnimation Duration="0:0:0.1" Storyboard.TargetName="plusSign" Storyboard.TargetProperty="(Path.Stroke).(SolidColorBrush.Color)" To="Black"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
I'm trying to do my own Slider Style in XAML, but i don't get it quite right. The VisualState x:Name="Pressed" is not being triggered.
...
<ControlTemplate TargetType="Slider">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal" />
<VisualState Name="MouseOver">
...
</VisualState>
<VisualState Name="Pressed">
<Storyboard>
<ColorAnimation Storyboard.TargetName="RepeatButtonValueBrush" Storyboard.TargetProperty="Color" To="{StaticResource PressedValueColor}" Duration="0"/>
<ColorAnimation Storyboard.TargetName="RepeatButtonRestBrush" Storyboard.TargetProperty="Color" To="{StaticResource PressedTrackColor}" Duration="0"/>
</Storyboard>
</VisualState>
<VisualState Name="Disabled">
...
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
...
</Grid>
</ControlTemplate>
...
What am I doing wrong?
Thanks
You need to call the VisualStateManager.GoToState method to change visual states. See this VisualStateManager and Triggers article.
How can I access the "image" from code behind in order to change its image source?
xaml code looks like this
<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"
mc:Ignorable="d"
x:Class="Demo.ChartButton"
d:DesignWidth="100" d:DesignHeight="100">
<UserControl.Resources>
<Style x:Key="ButtonStyle1" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0" To="White" Storyboard.TargetProperty="(UIElement.Effect).(DropShadowEffect.Color)" Storyboard.TargetName="image" d:IsOptimized="True" />
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(UIElement.Effect).(DropShadowEffect.ShadowDepth)" Storyboard.TargetName="image" d:IsOptimized="True"/>
<DoubleAnimation Duration="0" To="5" Storyboard.TargetProperty="(UIElement.Effect).(DropShadowEffect.BlurRadius)" Storyboard.TargetName="image" d:IsOptimized="True"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(UIElement.Effect).(DropShadowEffect.Opacity)" Storyboard.TargetName="image" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Duration="0" To="AntiqueWhite" Storyboard.TargetProperty="(UIElement.Effect).(DropShadowEffect.Color)" Storyboard.TargetName="image" d:IsOptimized="True"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(UIElement.Effect).(DropShadowEffect.Opacity)" Storyboard.TargetName="image" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(UIElement.Effect).(DropShadowEffect.Opacity)" Storyboard.TargetName="image" d:IsOptimized="True"/>
<ColorAnimation Duration="0" To="#FFAFAFAF" Storyboard.TargetProperty="(UIElement.Effect).(DropShadowEffect.Color)" Storyboard.TargetName="image" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Image x:Name="image" RenderTransformOrigin="0,0" Source="/Demo;component/spreadsheet-icon.png" >
<Image.Effect>
<DropShadowEffect ShadowDepth="0" BlurRadius="10" Color="Black" Opacity="1"/>
</Image.Effect>
</Image>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Button Content="" Margin="0,0,0,0" Style="{StaticResource ButtonStyle1}" Click="Button_Click" />
Any help is appreciated.
The only way to access this is to navigate the visual tree to locate the image. Using Linq-To-VisualTree, you can locate it as follows:
using LinqToVisualTree
private void Button_Click(object sender, EventArgs e)
{
Button button = sender as Button;
Image img = button.Descendants<Image>().Single() as Image;
img.Source = "..."
}
I am trying to create a Silverlight Toggle button style that would flip between a plus and a minus sign. Unfortunately it is always showing a minus sign. Can anyone tell me what's the problem with this style:
<Style x:Key="PlusMinusToggleButtonStyle" TargetType="ToggleButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Unchecked">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="UncheckedVisual" Storyboard.TargetProperty="Opacity" To="0" Duration="1" />
<DoubleAnimation Storyboard.TargetName="CheckedVisual" Storyboard.TargetProperty="Opacity" To="1" Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Checked">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="UncheckedVisual" Storyboard.TargetProperty="Opacity" To="1" Duration="0" />
<DoubleAnimation Storyboard.TargetName="CheckedVisual" Storyboard.TargetProperty="Opacity" To="0" Duration="1" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Image x:Name="UncheckedVisual" Source="plus.png" Stretch="None" />
<Image x:Name="CheckedVisual" Source="minus.png" Stretch="None" />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You need to expand on the DoubleAnimation, put in KeyFrame Animation in it. Also set the base opacity to 0 and then fade in the respective one you need. For example:
<VisualState x:Name="Checked">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="CheckedVisual" Storyboard.TargetProperty="Opacity">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
Everytime a state is changed, it goes back to the base state then to the state that was called. Because a togglebutton is always in an on or off state, it will not be in an invisible state.