private static void StopCurrentStoryboards(VisualStateGroup group, FrameworkElement element)
        {
            var currentStoryboards = group.GetCurrentStoryboards();

            foreach (var sb in currentStoryboards)
            {
                if (sb != null)
                {
                    sb.Remove(element);
                }
            }
            currentStoryboards.Clear();
        }
Exemplo n.º 2
0
        public static void StartNewThenStopOld(this VisualStateGroup group, FrameworkElement element, params Storyboard[] newStoryboards)
        {
            // Start the new Storyboards
            for (int index = 0; index < newStoryboards.Length; ++index)
            {
                if (newStoryboards[index] == null)
                {
                    continue;
                }

                newStoryboards[index].Begin();                 //.Begin(element, HandoffBehavior.SnapshotAndReplace, true);

                // Silverlight had an issue where initially, a checked CheckBox would not show the check mark
                // until the second frame. They chose to do a Seek(0) at this point, which this line
                // is supposed to mimic. It does not seem to be equivalent, though, and WPF ends up
                // with some odd animation behavior. I haven't seen the CheckBox issue on WPF, so
                // commenting this out for now.
                // newStoryboards[index].SeekAlignedToLastTick(element, TimeSpan.Zero, TimeSeekOrigin.BeginTime);
            }

            var _currentStoryboards = group.GetCurrentStoryboards();

            // Stop the old Storyboards
            for (int index = 0; index < _currentStoryboards.Count; ++index)
            {
                if (_currentStoryboards[index] == null)
                {
                    continue;
                }

                _currentStoryboards[index].Stop();                 // .Stop(element);
            }

            // Hold on to the running Storyboards
            _currentStoryboards.Clear();
            for (int index = 0; index < newStoryboards.Length; ++index)
            {
                _currentStoryboards.Add(newStoryboards[index]);
            }
        }
        /// <summary>
        /// Starts the specified <paramref name="newStoryboards"/> on the <paramref name="element"/>.
        /// Afterwards, the currently running storyboards of the visual state group are stopped.
        /// </summary>
        /// <param name="group">The group on which the storyboards will be started/stopped.</param>
        /// <param name="element">The element on which the storyboards will be run.</param>
        /// <param name="newStoryboards">The new storyboards to be run.</param>
        public static void StartNewAndStopOldStoryboards(
            this VisualStateGroup group, FrameworkElement element, params Storyboard[] newStoryboards)
        {
            if (group == null)
            {
                throw new ArgumentNullException(nameof(group));
            }

            // Stop old storyboards before starting new ones.
            StopCurrentStoryboards(group, element);

            // Merge all of the passed Storyboards into one single master storyboard.
            // This fixes a bug in the WPF animation system which sometimes causes certain
            // storyboards to not fire a completed event.
            // See https://stackoverflow.com/questions/5002501/visualstatemanager-not-working-as-advertised
            // for details.
            Storyboard masterStoryboard = BuildMasterStoryboard(newStoryboards);

            if (masterStoryboard != null)
            {
                masterStoryboard.Begin(element, HandoffBehavior.SnapshotAndReplace, true);
                group.GetCurrentStoryboards().Add(masterStoryboard);
            }
        }
        private static Storyboard GenerateDynamicTransitionAnimations(FrameworkElement root, VisualStateGroup group, VisualState newState, VisualTransition transition)
        {
            Storyboard dynamic = new Storyboard();

            if (transition != null && transition.GeneratedDuration != null)
            {
                dynamic.Duration = transition.GeneratedDuration;
            }
            else
            {
                dynamic.Duration = new Duration(TimeSpan.Zero);
            }

            Dictionary <TimelineDataToken, Timeline> currentAnimations    = FlattenTimelines(group.GetCurrentStoryboards());
            Dictionary <TimelineDataToken, Timeline> transitionAnimations = FlattenTimelines(transition != null ? transition.Storyboard : null);
            Dictionary <TimelineDataToken, Timeline> newStateAnimations   = FlattenTimelines(newState.Storyboard);

            // Remove any animations that the transition already animates.
            // There is no need to create an interstitial animation if one already exists.
            foreach (KeyValuePair <TimelineDataToken, Timeline> pair in transitionAnimations)
            {
                currentAnimations.Remove(pair.Key);
                newStateAnimations.Remove(pair.Key);
            }

            // Generate the "to" animations
            foreach (KeyValuePair <TimelineDataToken, Timeline> pair in newStateAnimations)
            {
                // The new "To" Animation -- the root is passed as a reference point for name
                // lookup.
                Timeline toAnimation = GenerateToAnimation(root, pair.Value, true);

                // If the animation is of a type that we can't generate transition animations
                // for, GenerateToAnimation will return null, and we should just keep going.
                if (toAnimation != null)
                {
                    toAnimation.Duration = dynamic.Duration;
                    dynamic.Children.Add(toAnimation);
                }

                // Remove this from the list of current state animations we have to consider next
                currentAnimations.Remove(pair.Key);
            }

            // Generate the "from" animations
            foreach (KeyValuePair <TimelineDataToken, Timeline> pair in currentAnimations)
            {
                Timeline fromAnimation = GenerateFromAnimation(pair.Value);
                if (fromAnimation != null)
                {
                    fromAnimation.Duration = dynamic.Duration;
                    string targetName = Storyboard.GetTargetName(pair.Value);
                    Storyboard.SetTargetName(fromAnimation, targetName);

                    // If the targetName of the existing Animation is known, then look up the
                    // target
                    DependencyObject target = String.IsNullOrEmpty(targetName) ?
                                              null : root.FindName(targetName) as DependencyObject;
                    if (target != null)
                    {
                        Storyboard.SetTarget(fromAnimation, target);
                    }

                    string propertyName = Storyboard.GetTargetProperty(pair.Value);
                    Storyboard.SetTargetProperty(fromAnimation, propertyName);
                    dynamic.Children.Add(fromAnimation);
                }
            }

            return(dynamic);
        }