Animating UserControl - wpf

I've made an opacity animation using Blend on one my two UserControls, deleted <UserControl.Resources>, <UserControl.Triggers> and Storyboard.TargetName from that, placed it in App.xaml and it looks like:
<Storyboard x:Key="Loaded">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" >
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:3" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
when I call it in code like this before setting the Content of my ContentControl:
Storyboard sb = FindResource("Loaded") as Storyboard;
sb.begin(uc1);
content.Content = uc1;
//and
Storyboard sb = FindResource("Loaded") as Storyboard;
sb.begin(uc2);
content.Content = uc2;
it works as expected. For the transform animation, I've deleted the TransformGroup as well in addition to those above and now it looks like:
<Storyboard x:Key="Unloaded">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:3" Value="-800"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
If I call it in the same way, I get this error:
System.InvalidOperationException: ''[Unknown]' property does not point to a DependencyObject in path '(0).(1)[3].(2)'.'
How to fix the problem?

You will need to add a RenderTransform to your UserControl which is similar to the Storyboard.TargetProperty which currently expects a TransformGroup with 4th child as TranslateTransform.
Add the below code to each of your two UserControls:
<UserControl x:Class="YourUserControl"
...>
<UserControl.RenderTransform>
<TransformGroup>
<RotateTransform/>
<ScaleTransform/>
<SkewTransform/>
<TranslateTransform/>
</TransformGroup>
</UserControl.RenderTransform>

Related

Setting Animation to trigger on a buttons second click not first click

I have a frame within my main page that I have set up to stretch/slide over on a button click. I do not want the frame to stretch/slide on the first button click but rather when the user clicks that same button a second time.
XAML:
<Storyboard x:Key="FrameSlide">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="currentPage">
<SplineDoubleKeyFrame KeyTime="0" Value="1"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.7" Value="1.217"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="currentPage">
<SplineDoubleKeyFrame KeyTime="0" Value="0"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.7" Value="-126"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="FrameSlideBack">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="currentPage">
<SplineDoubleKeyFrame KeyTime="0" Value="1.217"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.7" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="currentPage">
<SplineDoubleKeyFrame KeyTime="0" Value="-126"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.7" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="UIElement.MouseLeftButtonDown" SourceName="TransmitBTN">
<BeginStoryboard x:Name="FrameSlide" Storyboard="{StaticResource FrameSlide}"/>
</EventTrigger>
<EventTrigger RoutedEvent="UIElement.MouseLeftButtonDown" SourceName="PatientBTN">
<BeginStoryboard x:Name="FrameSlideBack" Storyboard="{StaticResource FrameSlideBack}"/>
</EventTrigger>
</Window.Triggers>
I've tried using the storyboard.stop() / storyboard.being() in my VB.net code for the button, but it seems like the xaml is over ridding the vb code. I've tired doing if statements where my frame is a certain width then do nothing else trigger the animation.
Not sure where to go from here.
Thanks
I am answering this in C# as i dont know VB but from what I am told you can change it easily?
The answer I can come with us is make an event on the button, button_click, within the class create a public property. In the event increment the property and when it reaches two, trigger your story board.
XAML for button event:
<Button x:Name="button" Content="Button" Click="Button_OnClick"
C# code:
public partial class StackOverFlowExample
{
public StackOverFlowExample()
{
InitializaComponent();
buttonClickCounter = 0;
}
public int buttonClickCounter {get; set;}
private void Button_Click(object sender, RoutedEventArgs e)
{
buttonClickCounter++;
if (buttonClickCounter == 2)
{
buttonClickCounter = 0;
Storyboard sb = Application.Current.Resources["FrameSlide"] as
Storyboard;
if (sb.IsSealed)
sb = sb.Clone();
Storyboard.SetTarget(sb, this.NextButton);
sb.Completed += delegate { };
sb.Begin();
}
e.Handled = true;
}
}

Animating over a Window

I have a program where the user needs to navigate through back and forth. Basically there's {Dashboard, Settings ... }
I implemented them using a User Control, so I have my Window, and my User Controls that load in it.
The page switcher code I used to navigate between them I found there (azerdark.wordpress.com/2010/04/23/multi-page-application-in-wpf)
What I want is to animate the way the User Controls navigate when they are loaded in my window.
The simplest thing I found would be to create a Frame over my Window and animate it .. which I did, but I'm having trouble raising the event that fires the animation. I tried animating on window loaded just for testing and it works fine, but when the User Controls are loaded in my windows the animation is not working.
Here's my code
XAML: {PageSwitcher - My Window where the User Controls are loaded}
<Window.Resources>
<Storyboard x:Key="FadeLeft">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="myFrame">
<EasingDoubleKeyFrame KeyTime="0" Value="900">
<EasingDoubleKeyFrame.EasingFunction>
<ExponentialEase EasingMode="EaseOut" Exponent="5"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<ExponentialEase EasingMode="EaseOut" Exponent="5"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="myFrame">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.5" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:0.6" Value="{x:Static Visibility.Hidden}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="myFrame">
<EasingDoubleKeyFrame KeyTime="0" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<PowerEase EasingMode="EaseOut" Power="2"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1">
<EasingDoubleKeyFrame.EasingFunction>
<PowerEase EasingMode="EaseOut" Power="2"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Frame x:Name="myFrame" Content="" Background="#FF8F4646" Visibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Disabled" RenderTransformOrigin="0.5,0.5">
<i:Interaction.Triggers>
<i:EventTrigger EventName="x:Static local:PageSwitcher.ainmate">
<ei:ControlStoryboardAction Storyboard="{StaticResource FadeLeft}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<Frame.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Frame.RenderTransform>
</Frame>
XAML.cs
public static readonly RoutedEvent animate = EventManager.RegisterRoutedEvent(
"Fade", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(PageSwitcher));
public event RoutedEventHandler Fade
{
add { AddHandler(animate, value); }
remove { RemoveHandler(animate, value); }
}
public void RaiseAnimateEvent()
{
RoutedEventArgs newEventArgs = new RoutedEventArgs(PageSwitcher.animate);
RaiseEvent(newEventArgs);
}
The event for the animation gets raised in my Switcher class just before Navigate is called to load the content of the User Control into my Window
XAML.cs {Switcher -- only sets the content of my window to the User Control passed when Navigate is called.}
public static void Switch(UserControl newPage)
{
pageSwitcher.Navigate(newPage);
pageSwitcher.RaiseAnimateEvent();
}
Is there anything wrong with my code? Why isn't the animation working?
The frame doesn't show when I navigate between the UserControls
Thanks for any help

how to use storyboards in WPF

I want to reuse a storyboad defined in a resourcedictionnary and referenced in App.xaml
<Storyboard x:Key="ShowWindowStoryboard">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
>
<EasingDoubleKeyFrame KeyTime="0:0:0.3"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"
>
<EasingDoubleKeyFrame KeyTime="0:0:0.3"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)"
>
<EasingDoubleKeyFrame KeyTime="0:0:0.3"
Value="1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
and here the code that gave an exception
Storyboard sb = (FindResource("ShowWindowStoryboard") as Storyboard).Clone();
DoubleAnimation da0 = sb.Children[0] as DoubleAnimation;
/* Exception here da0 is null*/
Storyboard.SetTarget(da0, uc);
DoubleAnimation da1 = sb.Children[1] as DoubleAnimation;
Storyboard.SetTarget(da1, uc);
DoubleAnimation da2 = sb.Children[2] as DoubleAnimation;
Storyboard.SetTarget(da2, uc);
sb.Begin();
i have also checked that sb.children.Count == 3 as expected.
You have to add a TransformGroup to the RenderTransform of your uc control. I will be adding a TransformGroup to an Image. The same will work for your control uc.
XAML
<Image Source="untitled.bmp" Name="ImgDemo">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform/>
</TransformGroup>
</Image.RenderTransform>
</Image>
If you have to add TransformGroup in code behind, you can use following before calling Story.Begin:
TransformGroup transformGroup = new TransformGroup();
transformGroup.Children.Add(new ScaleTransform(1,1));
uc.RenderTransform = transformGroup;
Your Storyboard.TargetProperty should reflect the signature of the object that you want the storyboard to be applied to. This is why you were facing the exception. Also, you might want to change your Storyboard a little to actually see the changes on the object. Like,
<Storyboard x:Key="ShowWindowStoryboard">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
>
<EasingDoubleKeyFrame KeyTime="0:0:0.3"
Value="0.5" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"
>
<EasingDoubleKeyFrame KeyTime="0:0:0.3"
Value="0.5" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)"
>
<EasingDoubleKeyFrame KeyTime="0:0:0.3"
Value="0.5" />
</DoubleAnimationUsingKeyFrames>
Note that the values are changed so that the animations will be noticeable. Finally, I do see that your code behind on calling the storyboard does not use proper casting. So you might wanna consider using the following,
Storyboard sb = (FindResource("ShowWindowStoryboard") as Storyboard).Clone();
DoubleAnimationUsingKeyFrames da0 = sb.Children[0] as DoubleAnimationUsingKeyFrames;
Storyboard.SetTarget(da0, ImgDemo);
DoubleAnimationUsingKeyFrames da1 = sb.Children[1] as DoubleAnimationUsingKeyFrames;
Storyboard.SetTarget(da1, ImgDemo);
DoubleAnimationUsingKeyFrames da2 = sb.Children[2] as DoubleAnimationUsingKeyFrames;
Storyboard.SetTarget(da2, ImgDemo);
sb.Begin();
Good luck!

How Run Xaml Animation With C# Code

I Have Animation In My ResourceDictionary But I Want Call Animation In My C# Code.
This ResourceDictionary Add To My Resources App
Example:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<BeginStoryboard x:Key="PuzzleFall">
<Storyboard Storyboard.TargetName="RenderT" Storyboard.TargetProperty="X">
<DoubleAnimationUsingKeyFrames Duration="0:0:3" BeginTime="0:0:0">
<SplineDoubleKeyFrame Value="0" KeySpline="1 0,0.95 0" KeyTime="0:0:3"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="0:0:3.06" Duration="0:0:1.5">
<SplineDoubleKeyFrame Value="50" KeySpline="0 1,0 1" KeyTime="0:0:1.5"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="0:0:3.08" Duration="0:0:1">
<SplineDoubleKeyFrame Value="0" KeySpline="1 0,1 0" KeyTime="0:0:1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="0:0:4.1" Duration="0:0:1">
<SplineDoubleKeyFrame Value="15" KeySpline="0 1,0 1" KeyTime="0:0:1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="0:0:4.15" Duration="0:0:0.5">
<SplineDoubleKeyFrame Value="0" KeySpline="1 0,1 0" KeyTime="0:0:0.5"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</ResourceDictionary>
Then I Want Run This Animation In C# Code.
Thanks.
You probably should not put the Storyboard which is the main component inside a BeginStoryboard especially if you use code. EIther way. you can get the Storyboard using FindResource.
In your current setup something like this:
var beginsb = (BeginStoryboard)FindResource("PuzzleFall");
var sb = beginsb.Storyboard;
sb.Begin();

Add image silverlight hovereffect from codebehind

I have a stackpanel that has a dynamic amount of images that are added programatically, Is there a way I can set a hover/click effect programatically on these images. I would like for the image to "glow" when clicked. How do i do that in silverlight? I've noticed the Image.Effect property, but I'm not really sure how to use it.
What you need to do is create a new usercontrol with the image control inside with the visualstates attached to it. This way, you can dynamically add the usercontrol to the stackpanel and have the animations being called without attaching them by events from your main app.
I used the DropShadowEffect on the Image.Effect to create a pulsating animation.
For eg. This is inside your usercontrol:
XAML
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ImageState">
<VisualState x:Name="NormalImageState">
<Storyboard>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="(UIElement.Effect).(DropShadowEffect.BlurRadius)" Storyboard.TargetName="image1" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
<VisualState x:Name="GlowingImageState">
<Storyboard AutoReverse="True">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Effect).(DropShadowEffect.BlurRadius)" Storyboard.TargetName="image1">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="20"/>
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Image Name="image1" MouseEnter="image1_MouseEnter" MouseLeave="image1_MouseLeave" >
<Image.Effect>
<DropShadowEffect Color="Red" BlurRadius="0" ShadowDepth="0"/>
</Image.Effect>
</Image>
C#
public ImageSource ImageSource
{
get;
set
{
image1.Source = value;
}
}
private void image1_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
{
VisualStateManager.GoToState(this, "GlowingImageState", true);
}
private void image1_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
VisualStateManager.GoToState(this, "NormalImageState", true);
}
Then you can add this usercontrol to your stack panel like so:
MyUC uc= new MyUC(); //control we just created
uc.ImageSource = sourceOfImg; //the source of the intended image
myStack.Children.Add(uc); //adding it to the stackpanel.
Tell me if this works.
You can use a transformation to create an animation to change the colour of your image when it is clicked.
Have a look at the MSDN page: Animation Overview. This page includes details on how to do this programmatically (Creating an Animation in Procedural Code).

Resources