I want to add animation to the loading user controls in a StackPanel.
So I add these lines to the existing project :
control.Loaded += UserControlLoaded;
and
public void UserControlLoaded(object sender, System.Windows.RoutedEventArgs e)
{
UserControl control = (UserControl)sender;
DoubleAnimation fadeInAnimation = new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(5)));
Storyboard.SetTarget(fadeInAnimation, control);
Storyboard.SetTargetProperty(fadeInAnimation, new PropertyPath(UIElement.OpacityProperty));
Storyboard sb = new Storyboard();
sb.Children.Add(fadeInAnimation);
sb.Begin();
}
It works good but I want to change it to scale the user control in both axis from 0 to 1 within 2 seconds but I can't find the code to set target property of the story board to the LayoutTransform X and Y axis !
The transform was made in MS Blend by this way :
How can I do it programmatically.
Thanks in advance for your kind attention.
The code that would animate the control's LayoutTransform depends on the kind of Transform used. Provided that it simply is a ScaleTransform, you could write this:
FrameworkElement control = sender as FrameworkElement;
ScaleTransform transform = control.LayoutTransform as ScaleTransform;
DoubleAnimation scaleAnimation =
new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(2)));
transform.BeginAnimation(ScaleTransform.ScaleXProperty, scaleAnimation);
transform.BeginAnimation(ScaleTransform.ScaleYProperty, scaleAnimation);
When the LayoutTransform was created with Blend, it is most certainly not simply a ScaleTransform, but a TransformGroup with a ScaleTransform as first child. You would then retrieve the ScaleTranform by something like this:
TransformGroup transformGroup = control.LayoutTransform as TransformGroup;
ScaleTransform transform = transformGroup.Children[0] as ScaleTransform;
And again i forgot the reason why animating a Transform like this won't work by means of a Storyboard. Instead of directly calling BeginAnimation on the ScaleTransform object, I've tried the code below, but without success.
DoubleAnimation xScaleAnimation =
new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(2)));
Storyboard.SetTarget(xScaleAnimation, transform);
Storyboard.SetTargetProperty(xScaleAnimation,
new PropertyPath(ScaleTransform.ScaleXProperty));
DoubleAnimation yScaleAnimation =
new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(2)));
Storyboard.SetTarget(yScaleAnimation, transform);
Storyboard.SetTargetProperty(yScaleAnimation,
new PropertyPath(ScaleTransform.ScaleYProperty));
Storyboard sb = new Storyboard();
sb.Children.Add(xScaleAnimation);
sb.Children.Add(yScaleAnimation);
sb.Begin();
Related
In WPF we can animate the back ground color for the particular control by using below code:
AssociatedObject.Background.BeginAnimation(SolidColorBrush.ColorProperty, ColorAnimation);
But I don't know how to animate the same in Silverlight and WinRT platforms.
The WPF code is (I think?) a shorthand for creating a storyboard, adding an animation and assigning its target, and running the storyboard. You can do the same in Silverlight like this:
var animation = new ColorAnimation
{
To = Colors.Black,
Duration = new Duration(TimeSpan.FromMilliseconds(500))
};
Storyboard.SetTarget(animation, AssociatedObject.Background);
Storyboard.SetTargetProperty(animation, new PropertyPath(SolidColorBrush.ColorProperty));
var sb = new Storyboard();
sb.Children.Add(animation);
sb.Begin();
I came across a different behaviour in Silverlight and WPF when an animated property values is held ("filled") after the animation has ended. The Remarks section in the documentation of the FillBehavior
property says
The filling behavior can create the illusion that a property is
unsettable at runtime if you are not careful about stopping unintended
animations. Attempting to change the animated value coming from a
filling animation in code will appear to have no effect until the
filling animation is stopped.
However, in Silverlight this seems not to be true. In the small example below I animate the Opacity of a filled Rectangle to zero when the "Fade Out" button is clicked. Although the animation's FillBehavior is set to HoldEnd, resetting the Opacity to 1 in the "Reset" button click handler works and the Button reappears. If I do the same in a WPF application it behaves as expected, namely clicking the "Reset" button has no visual effect.
My question is, has anybody else observed this behavior? Is it perhaps a bug in Silverlight, or am I missing something?
I'm using Silverlight 5 and WPF 4.5 here.
<StackPanel HorizontalAlignment="Center">
<Rectangle Name="rect" Width="200" Height="100" Fill="DarkGreen"/>
<Button Content="Fade Out" Click="FadeOutButtonClick"/>
<Button Content="Reset" Click="ResetButtonClick"/>
</StackPanel>
-
private void FadeOutButtonClick(object sender, RoutedEventArgs e)
{
var animation = new DoubleAnimation
{
To = 0d,
Duration = TimeSpan.FromSeconds(1),
FillBehavior = FillBehavior.HoldEnd
};
Storyboard.SetTargetProperty(animation, new PropertyPath(UIElement.OpacityProperty));
Storyboard.SetTarget(animation, rect);
var storyboard = new Storyboard();
storyboard.Children.Add(animation);
storyboard.Begin();
}
private void ResetButtonClick(object sender, RoutedEventArgs e)
{
rect.Opacity = 1d;
}
You can do a reverse animation on the reset :
private void ResetButtonClick(object sender, RoutedEventArgs e)
{
var animation = new DoubleAnimation
{
To = 1d,
Duration = TimeSpan.FromSeconds(0),
FillBehavior = FillBehavior.HoldEnd
};
Storyboard.SetTargetProperty(animation, new PropertyPath(UIElement.OpacityProperty));
Storyboard.SetTarget(animation, rect);
var storyboard = new Storyboard();
storyboard.Children.Add(animation);
storyboard.Begin();
Hope This will help.
I can resize datagrid in the window until I excecute this code:
// Handle the tabcontrol animation
DoubleAnimation dbTbViewsAnimation =
new DoubleAnimation(dToTabHeightParameter, new Duration(new TimeSpan(0,0,1)));
this.tbViews.BeginAnimation(TabControl.HeightProperty, dbTbViewsAnimation);
// Handle the tabcontrol animation
DoubleAnimation dbCurrentPlaylistHeightAnimation =
new DoubleAnimation(dToCurrentPlaylistParameter, new Duration(new TimeSpan(0, 0, 1)));
this.dgCurrentPlaylist.BeginAnimation(DataGrid.HeightProperty, dbCurrentPlaylistHeightAnimation);
What is the problem in this code and why it blocks the datagrid resizing?
thank you!
See Timeline.FillBehavior Property. The default value is HoldEnd. You could use a constructor overload to change this behavior.
DoubleAnimation dbTbViewsAnimation =
new DoubleAnimation(dToTabHeightParameter,
new Duration(new TimeSpan(0,0,1)),
FillBehavior.Stop);
FYI: How to: Set a Property After Animating It with a Storyboard
Background:
I'm loading images into a Stack Panel (called MainStack) displayed horizontally (for argument sake, 10 images) with only room for 4 images in view. As I load the images from the List I'm setting the width of each to 300 so they're all in the same size box.
I want to move the images from right to left using the Stack Panel's Margin (left) property. I want the appearance of scrolling left by exactly the same amount of the width of each image (looped with 4 second delay) until the last image is in view. Here's my code for the Margin animation:
Dim result As New Storyboard
Dim animation As New ThicknessAnimation
animation.From = MainStack.Margin
animation.EasingFunction = New PowerEase() With {.EasingMode = EasingMode.EaseInOut, .Power = 3}
animation.To = New Thickness(-300, 0, 0, 0)
animation.Duration = New Duration(TimeSpan.FromSeconds(1.5))
Storyboard.SetTarget(animation, MainStack)
Storyboard.SetTargetProperty(animation, New PropertyPath("Margin"))
result.Children.Add(animation)
result.Begin()
Strange thing is happening. The Stack Panel is moving to the left but only by about half the width of the image.
What is going on?!?
/* edit */
As per H.B. suggestion, I've tried to implement a TranslateTransform but not having much success.
Can anyone see any problems with this code?
Dim translatePosition = New Point(300, 0)
RenderTransform = New TranslateTransform()
Dim d As New Duration(New TimeSpan(0, 0, 0, 1, 30))
Dim x As New DoubleAnimation(translatePosition.X, d)
Storyboard.SetTarget(x, MainStack)
Storyboard.SetTargetProperty(x, New PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)"))
Dim sb As New Storyboard()
sb.Children.Add(x)
sb.Begin()
Nothing seems to be happening.
Ben
I think you should try putting your entire stackpanel in a canvas and just animating the Canvas.Left property to scroll the images.
Another option for you is to use a horizontal ListBox, then you can animate the ScrollViewer. If you want to try it this way, here's a link that may help: WPF - Animate ListBox.ScrollViewer.HorizontalOffset?.
I'm working on a 3D carousel of flat, square tiles that will contain information. I'm working on animating this carousel to rotate when a person presses Next and Previous buttons.
I've gotten it to work by using BeginAnimation on the Rotation property of the RotateTransform3D I applied to the carousel, but I can't seem to make a Storyboard version of the same animation work. The reason I need the Storyboard version is for the HandOffBehavior.Compose parameter because without it, multiple clicks of my next and previous buttons results in a misaligned carousel.
Here is the code for the Storyboard:
RotateTransform3D tempTransform = (RotateTransform3D)wheel.Transform;
AxisAngleRotation3D rotation = (AxisAngleRotation3D)tempTransform.Rotation;
Storyboard storyboard = new Storyboard();
DoubleAnimation animation = new DoubleAnimation();
animation.By = defaultAngle;
animation.Duration = TimeSpan.FromSeconds(.5);
Storyboard.SetTarget(animation, rotation);
Storyboard.SetTargetProperty(animation, new PropertyPath("Angle"));
storyboard.Children.Add(animation);
storyboard.Duration = animation.Duration;
storyboard.Begin(new FrameworkContentElement(), HandoffBehavior.Compose);
For some reason, this code results in absolutely nothing. I followed the examples I had to the letter, so I am quite frustrated. Any help is greatly appreciated. I am also completely open to using BeginAnimation if I can replicate HandOffBehavior.Compose.
My experience comes from 2D animation, but I guess the problem is the same.
For some stupid reason (probably relating to an unhealthy focus on XAML), Storyboards can only animate Freezable objects by looking them up by name. (See example in Storyboards Overview.) Thus although you provide a reference to your 'rotation' object when you call Storyboard.SetTarget(animation, rotation), the Storyboard only wants to remember and use a name, which it does not have.
The solution is:
Create a naming scope around the element that will govern the transform.
Call RegisterName() for each Freezable object being animated.
Pass the element to Storyboard.Begin()
Which would make your code look something like this (not tested):
FrameworkContentElement element = new FrameworkContentElement();
NameScope.SetNameScope(element, new NameScope());
RotateTransform3D tempTransform = (RotateTransform3D)wheel.Transform;
AxisAngleRotation3D rotation = (AxisAngleRotation3D)tempTransform.Rotation;
element.RegisterName("rotation", rotation);
Storyboard storyboard = new Storyboard();
DoubleAnimation animation = new DoubleAnimation();
animation.By = defaultAngle;
animation.Duration = TimeSpan.FromSeconds(.5);
Storyboard.SetTarget(animation, rotation);
Storyboard.SetTargetProperty(animation, new PropertyPath("Angle"));
storyboard.Children.Add(animation);
storyboard.Duration = animation.Duration;
storyboard.Begin(element, HandoffBehavior.Compose);
None of this is necessary in XAML because your objects are automatically registered.
EDIT: But then I worked out that you can simplify things by leaving out the Storyboard altogether:
var T = new TranslateTransform(40, 0);
Duration duration = new Duration(new TimeSpan(0, 0, 0, 1, 0);
DoubleAnimation anim = new DoubleAnimation(30, duration);
T.BeginAnimation(TranslateTransform.YProperty, anim);