So I searched for a solution and I didn't find something...
I have an application that use Storyboard for animations, and a button that create the animation and start it. looks like this:
DoubleAnimation animation = new DoubleAnimation
{
//properties
};
sb = new Storyboard();//sb is the Storyboard
sb.Children.Add(animation);
Storyboard.SetTargetName(animation, myControl.Name);
Storyboard.SetTargetProperty(animation, new PropertyPath(Canvas.TopProperty));
sb.Begin(this);
The problem is that when I click the button while the animation still running, it restart the animation, and I want it to "add it to the order" so when the animation finished it starts again over and over, the amount of times I clicked the button.
Instead of trying to change a storyboard that's already running I suggest you instead use just a list of animations.
Or storyboards if you need some functionality in storyboard like animating several things at once.
You can then add them to a list ( or queue even ).
Subscribe to the completed event of each.
Keep a currentIndex pointer so you know which one is running.
When the completed event is hit, unhook your event handler from the one just finished, hook the next one. Begin the next storyboard.
Related
What is my actual problem?
I want to stop Storyboard animation but keep current value of animated properties and unfreeze those properties.
What I have tried?
I tried storyboard.Pause() but this will keep the animated properties frozen. (changing values has no effect) I want to be able to release all properties from storyboard.
storyboard.Stop() doesn't work because it either sets value of animated properties to end or start of the animation depending on the FillBehavior. Although it will unfreeze the properties.
I tried clearing storyboard.Childern but it throws exception unless storyboard is fully stopped.
I tried to make new storyboard with duration 0 with same animations, this will stop previous animations and storyboard it self will finish in no time, but here are the problems
I should know what animations were added in last storyboard (I already solved this by storing dependency objects with property path in a List)
I have to retrieve current value of animated properties from property path.
I am stuck at the last one because this does not exist in UWP
string propertyPath = "(UIElement.Projection).(PlaneProjection.RotationY)";
// all animated properties are double
double value = (double)dependencyObject.GetValue(???);
GetValue requires DependencyProperty but i have a string.
Note: I just want a solution to my actual problem (top of this post).
I was able to solve this problem using following timeline
new DoubleAnimation { By = 0, Duration = TimeSpan.Zero }
With this timeline i don't have to know value of the properties. new storyboard on same elements and same property path's with duration 0 with this timeline will stop previous storyboard and keep their values. the new storyboard will also stop in no time and unfreeze the animated properties.
I have a WPF storyboard in my codebehind which runs with several color animations chained together. It works just fine, but in some scenarios I would like to be able to start the animation in the middle (e.g. 5 seconds into colorAnimation2) rather than always at the beginning. How would I go about this?
StoryBoard storyBoard = new StoryBoard;
// each animation runs for 10 seconds and starts 10 seconds after the previous one.
storyboard.Children.Add(colorAnimation1);
storyboard.Children.Add(colorAnimation2);
storyboard.Children.Add(colorAnimation3);
storyBoard.Begin();
Call the Seek() method just after calling storyBoard.Begin() to jump along the timeline by the given timespan.
storyBoard.Seek(TimeSpan.FromSeconds(15));
My WPF program's storyboard animations stutter ruining user experience (for example on adding larger number of items to ObservableCollection and ListBox being updated).
My idea was to make animation run smoother by dispatching them with higher priority so I tried
Storyboard sb = new Storyboard();
//all animations
this.Dispatcher.Invoke(() =>
{ sb.Begin();
}, System.Windows.Threading.DispatcherPriority.Send);
I thought there would be difference between "Send" as highest priority and "SystemIdle" as lowest, but there isn't.
I hope there is small problem in my understanding of the dispatcher and there is a simple fix, but I am open to any ideas of improving animation performance.
EDIT
Implemented on each animated control RenderTargetBitmap which takes screenshot on animation start and replaces complicated visual tree with one image control, and switches it back when animation is complete
Populating listbox that ruins my animation in Dispatcher with SystemIdle priority
Set framerate to 30
Checked in perfmon and nothing seems software rendered, RenderTier is 2
If I disable populating listbox completely everything runs smoothly
Listbox is populated like this
Task.Factory.StartNew(() =>
{
List<MyData> _f = new List<MyData>();
//populate _f
Dispatcher.BeginInvoke(new Action(() => {
_MyCollection.Clear();
_MyCollection.AddRange(_f); //Adding items without raising events *
}), DispatcherPriority.SystemIdle);
}
*I even use addRange for ObservableCollection from ObservableCollection : calling OnCollectionChanged with multiple new items
So im developing this app, where i got something that reminds alot about a list, but it doesn't use a list control or something. I add grids & rectangels to a scrollviewer, and when i doubletap a grip or a rectangel, it dissapears with a fade animation (which i also need help to do, as well as fade in, fast, one by one on app startup), and when that happens, i want the grid or rectangel beneath the one that faded out (or was removed, what is the best solution?), to be slided up, and replace the empty position. Please, do not misunderstand the question, i dont want you to make it for me, i want to know how since i absolutely cannot find ANY solution at all. It kind of works like google now for android and iphone. How can i do this the best way? Thank you SO much! Best regards, Erik
My DoubleAnimation to fade the grid:
DoubleAnimation fadeGrid = new DoubleAnimation();
fadeGrid.From = 0;
fadeGrid.To = 1;
fadeGrid.Duration = new Duration(TimeSpan.FromSeconds(0.5));
fadeGrid.AutoReverse = false;
1) Use animations for your fade out and slide up. For fade, you'll be doing a DoubleAnimation on the Opacity property. For sliding items up, you'll be doing an animiation on the TranslateTransform property. See these MSDN guides: http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206955(v=vs.105).aspx and http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.media.translatetransform(v=vs.105).aspx
2) For actually properly moving things up, you'll want to capture the Completed event from the animiation (http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.media.animation.timeline.completed(v=vs.105).aspx). When the animiation completes, remove those controls from the StackPanel inside the ScrollViewer, and undo any position animation you did on the items below it to animate them 'sliding' up.
3) After creating an animiation, you need to add it to a storyboard:
Storyboard sb = new Storyboard();
sb.Children.Add(fadeGrid);
Storyboard.SetTarget(fadeGrid, myRectangle);
Storyboard.SetTargetProperty(fadeGrid, new PropertyPath("(UIElement.Opacity)"));
sb.Begin();
The syntax for the propertypath but not be quite perfect, but you get the idea. You can see another example that specifically mentions opacity here: http://blogs.msdn.com/b/silverlight_sdk/archive/2008/03/21/silverlight-animations-a-walkthrough.aspx
I have a c# class, let's call it TwoButtonsHolder. In this class, I have 2 UIElements I wanna animate using StoryBoards. Let's call them ButtonA and ButtonB. Because I wanna have the both of them animate at the same time, I decided to put all their animations in one Storyboard object (or is there a better way?). So right now I'm trying to create the storyboard object in code behind, but I am stuck at the part where I have to define the target property. Normally when I declare animations I use code like this to set the property
Storyboard.SetTargetProperty(myDoubleAnimation,
new PropertyPath(UIElement.OpacityProperty));
now I have the UIElement within the target Object of the type TwoButtonsHolder. How do I create a storyboard and set the animation target property to TwoButtonsHolder.ButtonA.UIElement.OpacityProperty? Is this bad design for using a single storyboard to animate multiple objects in order to have animation that runs at the same time? (Just FYI, I wanna try this in code behind, don't wanna go into XAML yet because I find it too complicated and hard to learn IMHO). Thank you
Edit: Just wanna add that the 2 buttons have different animations, the only reason I'm putting them in the same storyboard is for them to start animating at the same time
It is absolutely no bad design to have animations for multiple objects in one Storyboard.
You would write it somehow like this:
var animationA = new DoubleAnimation(...);
Storyboard.SetTarget(animationA, ButtonA);
Storyboard.SetTargetProperty(animationA, new PropertyPath(UIElement.OpacityProperty));
var animationB = new DoubleAnimation(...);
Storyboard.SetTarget(animationB, ButtonB);
Storyboard.SetTargetProperty(animationB, new PropertyPath(UIElement.OpacityProperty));
var storyboard = new Storyboard();
storyboard.Children.Add(animationA);
storyboard.Children.Add(animationB);
storyboard.Begin();