WPF Second Animation (StoryBoard) doesn't work - c#

This is the scenario:
I Have a Grid and an Button. the Grid have a Show Boolean property. When user click on button, if Show=false then Grid become Visible. and when Show=true Grid become Collapse.
when it's visibility change, I do an animation for grid's Height with StoryBoard.
OK. every thing is fine. when user click the button, Grid appearing with animation. but when click again, the animation doesn't show and just Collapse occurred.
This is my code:
Storyboard growUpStory = new Storyboard();
Storyboard growDownStory = new Storyboard();
DoubleAnimation growUp, growDown;
In any method:
height = Container.DesiredSize.Height;
growUp = new DoubleAnimation
{
From = 0,
To = height > MaxHeight ? MaxHeight : height,
Duration = new Duration(TimeSpan.FromSeconds(1)),
AutoReverse = false
};
Container.Visibility = Visibility.Collapsed;
growDown = new DoubleAnimation
{
From = height > MaxHeight ? MaxHeight : height,
To = 0,
Duration = new Duration(TimeSpan.FromSeconds(1)),
AutoReverse = false
};
growUpStory.Children.Add(growUp);
growDownStory.Children.Add(growDown);
and when I invoke the event:
if (Show)
{
Storyboard.SetTarget(growUpStory, Container);
Storyboard.SetTargetProperty(growUpStory, new PropertyPath(Grid.HeightProperty));
growUpStory.Begin();
Container.Visibility = Visibility.Visible;
}
else
{
Storyboard.SetTarget(growDownStory, Container);
Storyboard.SetTargetProperty(growDownStory, new PropertyPath(Grid.HeightProperty));
growDownStory.Begin();
Container.Visibility = Visibility.Collapsed;
}
I Try many ways but was unable to resolve. Where is my problem? have you any idea? thanks.
I Can't use XAML here

Animations are asynchronous, which means you are collapsing the Visibility at the same time that you are starting the "growDownStory" animation.
Add some delay, based on how long you expect your "growDownStory" animation to run.
Example:
growDownStory.Begin();
await Task.Delay(1000); // allow time for the animation to perform its visual
Container.Visibility = Visibility.Collapsed;

Related

TextBlock animation for Opacity not working as expected

I have a UWP app project and I am trying to add a couple of DoubleAnimations and I am using below code:
private static void CreateStoryboardAnimation(StackPanel sp, ItemHelper item, EnumHelper.AddRemoveFavorites favType)
{
var image = (Image)sp.FindName("ImageView");
var tb = (TextBlock)sp.FindName("FavStatusTB");
if (image != null)
{
image.RenderTransform = new CompositeTransform();
//tb.RenderTransform = new CompositeTransform();
Storyboard tbStory = new Storyboard();
var tbAnimateOpacity = new DoubleAnimation()
{
From = 1.0,
To = 0.0,
Duration = new Duration(TimeSpan.FromMilliseconds(500)),
};
Storyboard.SetTarget(tbAnimateOpacity, tb);
Storyboard.SetTargetProperty(tbAnimateOpacity, "Opacity");
tbStory.Children.Add(tbAnimateOpacity);
Storyboard storyboard1 = new Storyboard();
storyboard1.Completed += async delegate
{
// set text
if (favType == EnumHelper.AddRemoveFavorites.Add)
{
tb.Text = "Added to favorites";
}
else
{
tb.Text = "Removed from favorites";
}
await Task.Delay(500);
// run 2nd animation
var storyboard2 = new Storyboard();
var translateYAnimation2 = new DoubleAnimation()
{
From = -20,
To = 0,
Duration = new Duration(TimeSpan.FromMilliseconds(700)),
};
Storyboard.SetTarget(translateYAnimation2, image);
Storyboard.SetTargetProperty(translateYAnimation2, "(UIElement.RenderTransform).(CompositeTransform.TranslateY)");
storyboard2.Children.Add(translateYAnimation2);
storyboard2.Begin();
tbStory.Begin();
};
DoubleAnimation translateYAnimation = new DoubleAnimation()
{
From = 0,
To = -20,
Duration = new Duration(TimeSpan.FromMilliseconds(500))
};
Storyboard.SetTarget(translateYAnimation, image);
Storyboard.SetTargetProperty(translateYAnimation, "(UIElement.RenderTransform).(CompositeTransform.TranslateY)");
storyboard1.Children.Add(translateYAnimation);
storyboard1.Begin();
}
}
The first time I run the animation it works fine but after that it doesn't. This code gets applied on GridView items as you can see below:
The image animation works fine, it goes up and then the TextBlock animation runs poorly. It is supposed to display the text for 500 milliseconds but it shows the text and then starts the animation to make the opacity go zero.
I want this text to be visible to the user for at least 500 milliseconds and then the animation should start. Is there something that I am missing? I also tried BeginTime property of DoubleAnimation but to no avail. Please share your suggestions. Thanks
I think the problem is with the fact that you are starting the opacity animation inside the Completed handler of the first "slide up" animation. It works the first time, because the Opacity of the TextBlock is 1.0, but after the first round it is 0.0 and flips to 1.0 only after the await Task.Delay(500); finishes. The easiest fix would be to set the opacity right after the if:
if (image != null)
{
tb.Opacity = 1; //add this line
...

Why ClipToBounds = false not work?

I do not want cut text of textblock. For this reason, I set viewBox.ClipToBounds to false, But it doesn't work.
Please tell me why ClipToBounds=false not work in this code:
private void Btn1_Click(object sender, RoutedEventArgs e)
{
Button button = new Button(); button.Background = Brushes.Red;
button.Width = 70; button.Height = 20;
Canvas.SetLeft(button, 100); Canvas.SetTop(button, 120);
button.Padding = new Thickness(1);
StackPanel stackPanel = new StackPanel();
Viewbox viewBox = new Viewbox();
viewBox.ClipToBounds = false;
Canvas canvas = new Canvas();
canvas.Width = button.Width; canvas.Height = button.Height;
TextBlock textBlock = new TextBlock();
textBlock.Text = "this is a test";
textBlock.FontSize = 15;
textBlock.FontFamily = new FontFamily("Arial");
textBlock.TextWrapping = TextWrapping.NoWrap;
textBlock.Foreground = Brushes.Green;
textBlock.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
textBlock.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
viewBox.Height = 20;
textBlock.IsHitTestVisible = false;
stackPanel.Children.Add(viewBox);
viewBox.Child = canvas;
canvas.Children.Add(textBlock);
button.Content = stackPanel;
Canvas MainCanvas = new Canvas();
MainCanvas.Children.Add(button);
this.Content = MainCanvas;
}
Screenhsot:
The screenshot below is what I want. :
ClipToBounds is false by default. However, clipping can still happen due to the way certain elements perform layout. Basically the way things work in WPF is that setting ClipToBounds = true will force things to clip. Leaving it set to false means that WPF determines how things should clip based on measure constraints and arrange rects.
If you look at the ArrangeCore and MeasureCore methods in FrameworkElement, you will see that there is quite a bit of logic determining whether something should clip. Of course, things that override FrameworkElement are free to render however they want, but generally they will obey the clipping rules established by the base class.
In the case of a TextBlock, it will definitely clip text that goes outside of its bounds if its size is constrained. You can see this by simply setting a Width on it, or placing it is a parent that has a Width set on it.
If you really need the text to render outside of the bounds of the control, you may have to consider something like writing a custom text rendering element.
Even then, it is still going to be clipped by its parent as soon as you place it in something else that clips. So, you could still end up stuck.
You could try placing the TextBlock on top of the button instead of inside of it, and setting its position to get it in the right place (maybe by binding it to something). This would work, but might get hard to manage if you need to do it too much.
Basically, you are trying to go against one of the hard-coded rules of WPF, so you are likely not going to find an easy way to do it. Perhaps you might want to reevaluate your design and determine if this behavior is really necessary for what you want to do, or if you can go about it in a different way.
Thanks to elgonzo and Xavier.
I realized that I should not put the canvas in the viewbox.
By 2 change my problem solved.
1 - Swap viewbox with canvas.
2 - Remove canvas.with = ...
This is correct code :
private void Btn1_Click(object sender, RoutedEventArgs e)
{
Button button = new Button(); button.Background = Brushes.Red;
button.Width = 70; button.Height = 20;
Canvas.SetLeft(button, 100); Canvas.SetTop(button, 120);
button.Padding = new Thickness(1);
StackPanel stackPanel = new StackPanel();
Viewbox viewBox = new Viewbox();
viewBox.ClipToBounds = false;
Canvas canvas = new Canvas();
// canvas.Width = button.Width; canvas.Height = button.Height;
TextBlock textBlock = new TextBlock();
textBlock.Text = "this is a test";
textBlock.FontSize = 15;
textBlock.FontFamily = new FontFamily("Arial");
textBlock.TextWrapping = TextWrapping.NoWrap;
textBlock.Foreground = Brushes.Green;
textBlock.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
textBlock.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
viewBox.Height = 20;
textBlock.IsHitTestVisible = false;
stackPanel.Children.Add(canvas);
viewBox.Child = textBlock;
canvas.Children.Add(viewBox);
button.Content = stackPanel;
Canvas MainCanvas = new Canvas();
MainCanvas.Children.Add(button);
this.Content = MainCanvas;
}

Using DoubleAnimation code behind in WinRT (XAML)

I have some problem. This is my code behind:
var s = new Storyboard();
var dAnimation = new DoubleAnimation();
dAnimation.RepeatBehavior = RepeatBehavior.Forever;
dAnimation.AutoReverse = true;
dAnimation.EnableDependentAnimation = true;
dAnimation.From = 200;
dAnimation.To = 300;
Storyboard.SetTarget(dAnimation, viewBox);
Storyboard.SetTargetProperty(dAnimation, "Width");
dAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(2000));
s.Children.Add(dAnimation);
s.Begin();
viewBox is on Canvas and has just a few property: Canvas.Left, Canvas.Top, Height and Width. Code from codebehind working great with Opacity, but not working with Width or Height. Codebehind work when user pointer is entered. I want do it without triggers. Found some solutions for Silverlight and WPF:
WinRT/Metro Animation in code-behind
they are not working. I dont undersstand why it work with opacity and didn't work with Width and Height Any ideas?
You cannot animate Width with a DoubleAnimation, you need to use a DoubleAnimationUsingKeyFrames.
var animation = new DoubleAnimationUsingKeyFrames();
var frame = new EasingDoubleKeyFrame { KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(2000)), Value = 300});
animation.KeyFrames.Add(frame);
Storyboard.SetTargetProperty(animation, "(FrameworkElement.Width)");
Storyboard.SetTarget(animation, viewBox);
Storyboard.Children.Add(animation);
I didn't check ViewBox,but I can with DoubleAnimation for Grid.
Code is like below
var s = new Storyboard();
var widthAnim = new DoubleAnimation()
{
To = w,
Duration=new Duration(TimeSpan.FromMilliseconds(duration))
};
widthAnim.EnableDependentAnimation = true;
Storyboard.SetTarget(widthAnim,elem);
Storyboard.SetTargetProperty(widthAnim,"Width");
s.Children.Add(widthAnim);
s.Begin();

Programmatic Move Animation in Windows Phone 8

I am working to create a Move Animation in windows. I want to move and object from one location to the other. Basically what I am trying to do is to FLIP the selected rectangle and then randomly swap the positions of two Rectangle objects the movement should be shown as an animation.
I have tried and achieved FLIP animation. But now if there are 4 rectangles in a grid, random two rectangles should exchange their positions followed by a move animation. I tried to use the below code. But it is not working.
It just creates a Rectangle in the center of the screen and nothing else.
1) Created a new project
2) Added the below code to the MainPage.xaml.cs file.
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
Loaded += Create_And_Run_Animation;
// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
}
private void Create_And_Run_Animation(object sender, EventArgs e)
{
// Create a red rectangle that will be the target
// of the animation.
Rectangle myRectangle = new Rectangle();
myRectangle.Width = 200;
myRectangle.Height = 200;
Color myColor = Color.FromArgb(255, 255, 0, 0);
SolidColorBrush myBrush = new SolidColorBrush();
myBrush.Color = myColor;
myRectangle.Fill = myBrush;
// Add the rectangle to the tree.
ContentPanel.Children.Add(myRectangle);
// Create a duration of 2 seconds.
Duration duration = new Duration(TimeSpan.FromSeconds(2));
// Create two DoubleAnimations and set their properties.
DoubleAnimation myDoubleAnimation1 = new DoubleAnimation();
DoubleAnimation myDoubleAnimation2 = new DoubleAnimation();
myDoubleAnimation1.Duration = duration;
myDoubleAnimation2.Duration = duration;
Storyboard sb = new Storyboard();
sb.Duration = duration;
sb.Children.Add(myDoubleAnimation1);
sb.Children.Add(myDoubleAnimation2);
Storyboard.SetTarget(myDoubleAnimation1, myRectangle);
Storyboard.SetTarget(myDoubleAnimation2, myRectangle);
// Set the attached properties of Canvas.Left and Canvas.Top
// to be the target properties of the two respective DoubleAnimations.
Storyboard.SetTargetProperty(myDoubleAnimation1, new PropertyPath("(Canvas.Left)"));
Storyboard.SetTargetProperty(myDoubleAnimation2, new PropertyPath("(Canvas.Top)"));
myDoubleAnimation1.To = 200;
myDoubleAnimation2.To = 200;
// Make the Storyboard a resource.
ContentPanel.Resources.Add("unique_id", sb);
// Begin the animation.
sb.Begin();
}
}
I haven't added anything in the xaml file. that is just as it is. Is there anything that i need to add to the xaml file for the animation to run properly. ?
Please Help
Better late than never ;-).
Just got the problem myself, you need to add
myDoubleAnimation1.EnableDependentAnimation = true;
myDoubleAnimation2.EnableDependentAnimation = true;
to your code to force WinRT to do execute animation - otherwise it deems your animation to be not worthy due to possible performance issues ... sigh.
Source: https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.media.animation.doubleanimation.enabledependentanimation.aspx

Animate Popup before closing

I'm making a program for Windows 8 in WinRT and I'm having some trouble with the Popup-class.
The content in the popup has a fancy intro-animation when it is opened. I'd like to animate the content in the popup right before it closes, but haven't found out how.
Any ideas?
Thanks in advance
EDIT: This is an example for what I'm trying to do. The Closed-eventhandler is obviously too late for doing anything before it closes. But you get the point.
Popup popup = new Popup();
SolidColorBrush brush = new SolidColorBrush(Colors.Red);
Ellipse ell = new Ellipse() { Fill = brush, Width = 300, Height = 300 };
popup.Child = ell;
popup.Opened += (sender, e) =>
{
ColorAnimation anim = new ColorAnimation() { To = Colors.Blue };
Storyboard.SetTarget(anim, brush);
Storyboard.SetTargetProperty(anim, "Color");
Storyboard sb = new Storyboard();
sb.Children.Add(anim);
sb.Begin();
};
popup.Closed += (sender, e) =>
{
ColorAnimation anim = new ColorAnimation() { To = Colors.Green };
Storyboard.SetTarget(anim, brush);
Storyboard.SetTargetProperty(anim, "Color");
Storyboard sb = new Storyboard();
sb.Children.Add(anim);
sb.Begin();
};
popup.IsOpen = true;
The problem here is that the popup has only 2 visibility states (isopen =true/false). when IsOpen is set to false (i.e. closed) the popup's visibility is set to Collapsed and the animation is not played. What I would suggest is:
The popup obviously has a close button to close it, right? So in that close button's click event, start the animation. Then listen to the completed event on the storyboard and set the popup.IsOpen=false there
sb.Completed += SomeEventHandler

Categories

Resources