private void OnCurrentTransitionStoryboardCompleted(VisualTransition currentTransition)
 {
     VisualStateSource.Verbose("Explicit storyboard completed. State: {0}", StateName);
     if (currentTransition.GetDynamicStoryboardCompleted() &&
         ShouldRunStateStoryboard())
     {
         VisualStateSource.Verbose("Running ToState storyboards.");
         Group.StartNewAndStopOldStoryboards(StateGroupsRoot, ToState.Storyboard);
     }
     currentTransition.SetExplicitStoryboardCompleted(true);
 }
        private void PlayTransitionAnimations(
            VisualTransition currentTransition, Storyboard dynamicTransitionStoryboard)
        {
            // Create these local event handlers, so that we can pass the local variables
            // to the actual handler functions, while also being able to de-register the event
            // handlers again, to not create memory leaks.
            EventHandler dynamicStoryboardCompletedHandler = null;
            EventHandler currentStoryboardCompletedHandler = null;

            dynamicStoryboardCompletedHandler = (sender, e) =>
            {
                dynamicTransitionStoryboard.Completed -= dynamicStoryboardCompletedHandler;
                OnDynamicTransitionStoryboardCompleted(dynamicTransitionStoryboard, currentTransition);
            };
            currentStoryboardCompletedHandler = (sender, e) =>
            {
                currentTransition.Storyboard.Completed -= currentStoryboardCompletedHandler;
                OnCurrentTransitionStoryboardCompleted(currentTransition);
            };

            // Play the dynamically created storyboard every single time.
            VisualStateSource.Verbose("Preparing dynamically generated transition storyboard.");
            currentTransition.SetDynamicStoryboardCompleted(false);
            dynamicTransitionStoryboard.Completed += dynamicStoryboardCompletedHandler;

            // If a storyboard has been defined INSIDE the VisualTransition
            // (-> explicit storyboard), play that aswell.
            if (currentTransition.Storyboard != null &&
                currentTransition.GetExplicitStoryboardCompleted())
            {
                VisualStateSource.Verbose("Preparing explicit storyboard defined in transition.");
                currentTransition.SetExplicitStoryboardCompleted(false);
                currentTransition.Storyboard.Completed += currentStoryboardCompletedHandler;
            }

            VisualStateSource.Verbose("Starting storyboards.");
            Group.StartNewAndStopOldStoryboards(
                StateGroupsRoot,
                currentTransition.Storyboard,
                dynamicTransitionStoryboard);
        }
        private static bool GoToStateInternal(Control control, FrameworkElement element, VisualStateGroup group, VisualState state, bool useTransitions)
        {
            if (element == null)
            {
                throw new ArgumentNullException("element");
            }

            if (state == null)
            {
                throw new ArgumentNullException("state");
            }

            if (group == null)
            {
                throw new InvalidOperationException();
            }

            //VisualState lastState = group.CurrentState;
            VisualState lastState = group.GetCurrentState();

            if (lastState == state)
            {
                return(true);
            }

            // Get the transition Storyboard. Even if there are no transitions specified, there might
            // be properties that we're rolling back to their default values.
            VisualTransition transition = useTransitions ? ExtendedVisualStateManager.GetTransition(element, group, lastState, state) : null;

            // Generate dynamicTransition Storyboard
            Storyboard dynamicTransition = GenerateDynamicTransitionAnimations(element, group, state, transition);

            // If the transition is null, then we want to instantly snap. The dynamicTransition will
            // consist of everything that is being moved back to the default state.
            // If the transition.Duration and explicit storyboard duration is zero, then we want both the dynamic
            // and state Storyboards to happen in the same tick, so we start them at the same time.
            if (transition == null || (transition.GeneratedDuration == DurationZero &&
                                       (transition.Storyboard == null || transition.Storyboard.Duration == DurationZero)))
            {
                // Start new state Storyboard and stop any previously running Storyboards
                if (transition != null && transition.Storyboard != null)
                {
                    group.StartNewThenStopOld(element, transition.Storyboard, state.Storyboard);
                }
                else
                {
                    group.StartNewThenStopOld(element, state.Storyboard);
                }

                // Fire both CurrentStateChanging and CurrentStateChanged events
                //group.RaiseCurrentStateChanging(element, lastState, state, control);
                //group.RaiseCurrentStateChanged(element, lastState, state, control);
            }
            else
            {
                // In this case, we have an interstitial storyboard of duration > 0 and/or
                // explicit storyboard of duration >0 , so we need
                // to run them first, and then we'll run the state storyboard.
                // we have to wait for both storyboards to complete before
                // starting the steady state animations.
                transition.SetDynamicStoryboardCompleted(false);                  //transition.DynamicStoryboardCompleted = false;

                // Hook up generated Storyboard's Completed event handler
                dynamicTransition.Completed += delegate(object sender, Object e)
                {
                    // transition.ExplicitStoryboardCompleted) &&
                    if ((transition.Storyboard == null || transition.GetExplicitStoryboardCompleted()) &&

                        // If the element or control is removed from the tree, then the new
                        // storyboards will not be able to resolve target names. Thus,
                        // if the element or control is unloaded, don't start the new
                        // storyboards.
                        //(element.IsLoaded && (control == null || control.IsLoaded)))
                        (element.Parent != null && (control == null || control.Parent != null)))
                    {
                        group.StartNewThenStopOld(element, state.Storyboard);
                    }

                    //group.RaiseCurrentStateChanged(element, lastState, state, control);
                    transition.SetDynamicStoryboardCompleted(true);                      //transition.DynamicStoryboardCompleted = true;
                };

                // if (transition.Storyboard != null && transition.ExplicitStoryboardCompleted == true)
                if (transition.Storyboard != null && transition.GetExplicitStoryboardCompleted() == true)
                {
                    EventHandler <Object> transitionCompleted = null;
                    transitionCompleted = new EventHandler <Object>(delegate(object sender, Object e)
                    {
                        if (transition.GetDynamicStoryboardCompleted() &&

                            // If the element or control is removed from the tree, then the new
                            // storyboards will not be able to resolve target names. Thus,
                            // if the element or control is unloaded, don't start the new
                            // storyboards.
                            //(element.IsLoaded && (control == null || control.IsLoaded)))
                            (element.Parent != null && (control == null || control.Parent != null)))
                        {
                            group.StartNewThenStopOld(element, state.Storyboard);
                        }

                        //group.RaiseCurrentStateChanged(element, lastState, state, control);
                        transition.Storyboard.Completed -= transitionCompleted;
                        transition.SetExplicitStoryboardCompleted(true);
                    });

                    // hook up explicit storyboard's Completed event handler
                    transition.SetExplicitStoryboardCompleted(false);
                    transition.Storyboard.Completed += transitionCompleted;
                }

                // Start transition and dynamicTransition Storyboards
                // Stop any previously running Storyboards
                group.StartNewThenStopOld(element, transition.Storyboard, dynamicTransition);
                //group.RaiseCurrentStateChanging(element, lastState, state, control);
            }

            //group.CurrentState = state;
            group.SetCurrentState(state);

            return(true);
        }