I have a Button:
<Button x:Name="button" Click="{x:Bind ViewModel.OnButtonClick}">
<Button.Projection>
<PlaneProjection RotationZ="50"/>
</Button.Projection>
<Button.Triggers>
<EventTrigger>
<BeginStoryboard>
<Storyboard x:Name="Storyboard1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationZ)" Storyboard.TargetName="button">
<EasingDoubleKeyFrame KeyTime="0" Value="50"/>
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="320"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
And I use MVVM pattern so after click on the button, the method is called. I want also to start a storyboard but I found only this solution for MVVM pattern, because I can't reference Storyboard in my ViewModel (so I can't start it there).
Is there any way to modify this Storyboard to start only on button click? Now it starts when the application starts.
There is couple of ways you can do it - define your Storyboard in resources and then just begin from code, use VisualStates for this within button's Style or even do everything in xaml by using Behaviors extension. The latter can look like this (first add reference to Behaviors XAML):
<!--add needed namespaces-->
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:icore="using:Microsoft.Xaml.Interactions.Core"
xmlns:imedia="using:Microsoft.Xaml.Interactions.Media"
<Button x:Name="button" >
<Button.Projection>
<PlaneProjection RotationZ="50"/>
</Button.Projection>
<interactivity:Interaction.Behaviors>
<icore:EventTriggerBehavior EventName="Click" SourceObject="{Binding ElementName=button}">
<imedia:ControlStoryboardAction>
<imedia:ControlStoryboardAction.Storyboard>
<Storyboard x:Name="Storyboard1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationZ)" Storyboard.TargetName="button">
<EasingDoubleKeyFrame KeyTime="0" Value="50"/>
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="320"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</imedia:ControlStoryboardAction.Storyboard>
</imedia:ControlStoryboardAction>
</icore:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</Button>
Related
I have the following xaml:
<Button Content="{Binding Header}" Background="Blue" Name="PanelHeader">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="Stackpanel"
Storyboard.TargetProperty="Height"
From="0" To="100" Duration="0:0:3" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
I want to move the storyboard animation to the stack panel declaration and simply invoke that animation from the button click.
Most examples I've found resort to using the viewmodel or other codebehind interjections.
this example doesn't use code behind nor ViewModel
http://www.java2s.com/Tutorial/VB/0290__Windows-Presentation-Foundation/StartandstopanAnimationwithButtonactions.htm
I have a storyboard animation of a control scaling up and down and I want to get a propertychanged callback when the scale value changes in the storyboard.
<Storyboard x:Name="ScaleLoop" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)" Storyboard.TargetName="ScalingObject" EnableDependentAnimation="True">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
the animation above is simple but in the future I plan to animate a more complex one.
<Canvas x:Name="ScalingObject">
<Canvas.RenderTransform>
<CompositeTransform ScaleY="1"/>
</Canvas.RenderTransform>
</Canvas>
this is the callback that I am using:
long handle = this.ScalingObject.RegisterPropertyChangedCallback(Canvas.RenderTransformProperty, new DependencyPropertyChangedCallback(this.ChangeState));
but this only gets fired once.
Is this is best way to do this?
Any help would be great.
Thanks,
B
It seems the Canvas.RenderTransformProperty can not fire the event.
You should be able to use the CompositeTransform.ScaleYProperty to set to the RegisterPropertyChangedCallback method. When the value of the CompositeTransform.ScaleYProperty is changed, the ChangeState event will be fired.
For example:
var compositeTransform = (CompositeTransform)ScalingObject.RenderTransform;
long handle = compositeTransform.RegisterPropertyChangedCallback(CompositeTransform.ScaleYProperty, new DependencyPropertyChangedCallback(this.ChangeState));
Issue
The issue I am having is when a user clicks a button I want the button to start flashing from 100% visible to around 20% visible and the background of the WPF window to change colors from #ffffff to #d6786a and this should happen untill the button is clicked again. Then the animations should stop.
Code
I have done a bit of diging around to find where somone has done this and I can't seem to see anything. The code i have at the moment is as follows.
Here is the button I want to flash from 100% visible to 20% visible when clicked:
<Button Name="button2" Style="{DynamicResource NoChromeButton}" Visibility="{Binding VisableState, Converter={StaticResource BoolToVis}}" ToolTip="Start Live Stream" Command="{Binding PlayStream}" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="5" Height="22" Width="22" >
<Image Source="../Images/recordicon.png"/>
</Button>
I have tried to add a storyboard into the button and it just didn't work:
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard BeginTime="00:00:00"
RepeatBehavior="Forever"
Storyboard.TargetName="button2"
Storyboard.TargetProperty="(Visibility)">
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Button.Triggers>
I am new to WPF so going into animation is more difficult for me. If anyone could give me a little help on this stage it would be great.
Define animations in resources for example like this
<Window x:Name="window" x:Class="WpfApplication1.MainWindow"
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:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Storyboard x:Key="FlashButton" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="button">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="0.2"/>
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="ChangeColor">
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" Storyboard.TargetName="grid">
<EasingColorKeyFrame KeyTime="0:0:1" Value="Red"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="ChangeColor2">
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" Storyboard.TargetName="grid">
<EasingColorKeyFrame KeyTime="0:0:1" Value="White"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Grid x:Name="grid" Background="White">
<Button x:Name="button" Content="Button" Margin="10,10,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Width="75" Click="button_Click"/>
</Grid>
and create handler for button click
private bool isRunning;
private void button_Click(object sender, RoutedEventArgs e)
{
var flashButton = FindResource("FlashButton") as Storyboard;
var changeColor = FindResource("ChangeColor") as Storyboard;
var changeColor2 = FindResource("ChangeColor2") as Storyboard;
if (isRunning)
{
flashButton.Stop();
changeColor2.Begin();
isRunning = false;
}
else
{
flashButton.Begin();
changeColor.Begin();
isRunning = true;
}
}
To change "visibility to around 20%" you have to animate Opacity property (double type from 0.0 to 1.0) not Visibility (enum with 3 values, see msdn).
The goal can be easily achieved if you can use ToggleButton (because of its nice Checked and Unckecked routed events):
<ToggleButton>
<ToggleButton.Triggers>
<EventTrigger RoutedEvent="ToggleButton.Checked">
<BeginStoryboard x:Name="storyboard">
<Storyboard RepeatBehavior="Forever"
AutoReverse="True">
<DoubleAnimation Storyboard.TargetProperty="Opacity"
To="0.2"
Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="ToggleButton.Unchecked">
<StopStoryboard BeginStoryboardName="storyboard" />
</EventTrigger>
</ToggleButton.Triggers>
</ToggleButton>
I am building Windows Store Application (Winrt, Metro, Windows 8 app). I try give images in gridview animation: after image is loaded from web and opened it populates its cell.
I have storyboard for that:
<Storyboard x:Name="PopupImageStoryboard">
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="image">
<EasingDoubleKeyFrame KeyTime="0" Value="100"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="240"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True" Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="image">
<EasingDoubleKeyFrame KeyTime="0" Value="100"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="240"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
And I have such C# code for handling event that image loaded and opened:
private void Image_ImageOpened(object sender, RoutedEventArgs e)
{
Storyboard.SetTarget(PopupImageStoryboard, sender as Image);
PopupImageStoryboard.Begin();
}
It does not work, I can not change target and rerun same storyboard while it is running. But I want multiple images run this animation simultaneously. Can you recommend any solution for animation reuse ?
You should remove this from each of the child animations:
Storyboard.TargetName="image"
Then also I think a single Storyboard might not be possible to be used on two target elements at the same time, so the solution for that would be to put it in a DataTemplate, e.g.
<Page.Resources>
<DataTemplate
x:Name="myStoryboard">
<Storyboard ... />
</DataTemplate>
</Page.Resources>
Then in code you would say
var sb = (Storyboard)myStoryboard.LoadContent();
Storyboard.SetTarget(sb, sender as Image);
sb.Begin();
BTW - do not animate Width and Height properties. This is almost certainly not the best idea in your case. You should animate your RenderTransform properties instead, e.g. targeting ScaleTransform's ScaleX and ScaleY properties. If an animation is a dependent - it will cause layout updates in each frame which is very inefficient and will degrade your animation frame rate.
*EDIT
A better solution then would look like this:
<Page.Resources>
<DataTemplate
x:Name="myStoryboardTemplate">
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="ScaleX"
From="0.5"
To="1.0"
Duration="0:0:0.4">
<DoubleAnimation.EasingFunction>
<BackEase
Amplitude="2"
EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation
Storyboard.TargetProperty="ScaleY"
From="0.5"
To="1.0"
Duration="0:0:0.4">
<DoubleAnimation.EasingFunction>
<BackEase
Amplitude="2"
EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</DataTemplate>
</Page.Resources>
...
<Image
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="620"
Height="300"
Source="Assets/SplashScreen.png"
RenderTransformOrigin="0.5,0.5"
Stretch="Fill">
<Image.RenderTransform>
<ScaleTransform
x:Name="imageScaleTransform" />
</Image.RenderTransform>
</Image>
...
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var sb = (Storyboard)myStoryboardTemplate.LoadContent();
Storyboard.SetTarget(sb, imageScaleTransform);
sb.Begin();
}
I'm trying to skin a ScrollViewer in WPF using XAML but have been faced with a challenge. Normally my ScrollBars are hidden, but when the user start panning the screen they become visible. I have implemented this feature using ScrollChanged as follows:
<!-- Storyboards -->
<Storyboard x:Key="uiStoryboardFader">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="1.0" />
<EasingDoubleKeyFrame KeyTime="0:0:2.0" Value="1.0" />
<EasingDoubleKeyFrame KeyTime="0:0:2.3" Value="0.0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<!-- Style Declaration -->
<!-- Control Template -->
<ScrollBar x:Name="PART_VerticalScrollBar" Opacity="0.0" />
<ScrollBar x:Name="PART_HorizontalScrollBar" Opacity="0.0" />
<!-- Control Template Triggers -->
<EventTrigger RoutedEvent="ScrollViewer.ScrollChanged">
<BeginStoryboard Storyboard="{StaticResource uiStoryboardFader}"
Storyboard.TargetName="PART_VerticalScrollBar" />
<BeginStoryboard Storyboard="{StaticResource uiStoryboardFader}"
Storyboard.TargetName="PART_HorizontalScrollBar" />
</EventTrigger>
<!-- Closing -->
What this does is change the opacity of the entire ScrollViewer, even though I set the TargetName to "PART_VerticalScrollBar" and "PART_HorizontalScrollBar". However when I manually set the TargetName inside the Storyboard declaration, everything works as expected. Is there anyway I can make this work by assigning the TargetName inside BeginStoryboard?
I take it you just do not want to copy-paste the animation? What you try to do will probably never work out, the value of that property is not inherited and you need two storyboards anyway, you cannot start the same storyboard twice (let alone on different controls).
This is how you can at least retain one instance of the animation:
<DoubleAnimationUsingKeyFrames x:Key="Animation"
Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="1.0" />
<EasingDoubleKeyFrame KeyTime="0:0:2.0" Value="1.0" />
<EasingDoubleKeyFrame KeyTime="0:0:2.3" Value="0.0" />
</DoubleAnimationUsingKeyFrames>
<!-- ... -->
<EventTrigger RoutedEvent="ScrollViewer.ScrollChanged">
<BeginStoryboard>
<Storyboard Storyboard.TargetName="PART_VerticalScrollBar">
<StaticResourceExtension ResourceKey="Animation" />
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard Storyboard.TargetName="PART_HorizontalScrollBar">
<StaticResourceExtension ResourceKey="Animation" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>