Пример #1
0
        private static bool TransitionToState(
            FrameworkElement control,
            FrameworkElement stateGroupsRoot,
            string stateName,
            VisualStateGroup group,
            VisualState state,
            bool useTransitions)
        {
            VisualStateSource.Info(
                "Changing visual state from \"{0}\" to \"{1}\" on control {2} with root element {3}.",
                group.GetCurrentState()?.Name ?? group.CurrentState?.Name,
                stateName,
                control,
                stateGroupsRoot);

            // We offload the actual transitioning logic into multiple different StateSwitchers,
            // so that this class doesn't become cluttered.
            // Simply call them in order and check if one of them managed to transition to a new state.
            bool couldTransitionToState = false;

            couldTransitionToState |= new SetterVisualStateSwitcher().GoToState(
                control, stateGroupsRoot, stateName, group, state, useTransitions);
            couldTransitionToState |= new AnimationVisualStateSwitcher().GoToState(
                control, stateGroupsRoot, stateName, group, state, useTransitions);

            group.SetCurrentState(state);
            return(couldTransitionToState);
        }
        private void ApplySetter(Setter setter)
        {
            DependencyObject setterTarget = FindSetterTarget(setter);

            if (setterTarget != null)
            {
                if (setter.Value is Binding binding)
                {
                    BindingOperations.SetBinding(setterTarget, setter.Property, binding);
                }
                else
                {
                    // We are dealing with a "normal" .NET property value.
                    //
                    // SetCurrentValue doesn't change the property source, but changes the value until
                    // reset.
                    // This is ideal, as long as we reset the property again
                    // (which is done in the RemoveSetter method(s)).
                    setterTarget.SetCurrentValue(setter.Property, setter.Value);
                }

                VisualStateSource.Verbose(
                    "Setting property {0} to {1} on element {2}.",
                    setter.Property.Name,
                    setter.Value,
                    setterTarget);
            }
        }
Пример #3
0
        private bool ShouldTransitionToState(FrameworkElement control, VisualStateGroup group, VisualState state)
        {
            // No need to transition, if we are already at the target state.
            if ((group.GetCurrentState() ?? group.CurrentState) == state)
            {
                VisualStateSource.Verbose(
                    "Not changing to visual state {0}, because the control \"{1}\" is already at that state.",
                    state.Name,
                    control
                    );
                return(false);
            }

            // The ExtendedVisualState can have a set of Conditions, which need to apply.
            if (state is ExtendedVisualState extendedState &&
                !extendedState.AreConditionsApplyingToControl(control))
            {
                VisualStateSource.Verbose(
                    "Not changing to visual state {0}, because one of " +
                    "the state's conditions doesn't apply.",
                    state.Name
                    );
                return(false);
            }

            return(true);
        }
        private void RemoveSetter(Setter setter)
        {
            // InvalidateProperty forces the previously changed property to be
            // re-evaluated. This resets any previous changes.
            DependencyObject setterTarget = FindSetterTarget(setter);

            if (setterTarget != null)
            {
                if (setter.Value is Binding)
                {
                    BindingOperations.ClearBinding(setterTarget, setter.Property);
                }
                else
                {
                    // A normal .NET value can simply be invalidated. The DP remembers the previous
                    // value.
                    setterTarget.InvalidateProperty(setter.Property);
                }

                VisualStateSource.Verbose(
                    "Removed visual state setter for property {0} from element {1}.",
                    setter.Property.Name,
                    setterTarget);
            }
        }
 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 DependencyObject FindSetterTarget(Setter setter)
        {
            // If no target name is specified, the setter referes (by convention) to the control.
            if (string.IsNullOrEmpty(setter.TargetName))
            {
                return(Control);
            }

            // Try to locate the target in the template part, or in the control itself.
            var target = StateGroupsRoot.FindName(setter.TargetName) as DependencyObject ??
                         Control.FindName(setter.TargetName) as DependencyObject;

            if (target == null)
            {
                VisualStateSource.Warn(
                    "Couldn't find the visual state setter target \"{0}\".", setter.TargetName);
            }

            return(target);
        }
        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);
        }
        /// <summary>
        /// Transitions to another state by generating dynamic transitioning animations.
        /// </summary>
        /// <returns>
        /// Always returns <c>true</c>.
        /// </returns>
        protected override bool GoToStateCore()
        {
            VisualTransition currentTransition           = GetCurrentVisualTransition();
            Storyboard       dynamicTransitionStoryboard = CreateDynamicTransitionStoryboard(currentTransition);

            if (currentTransition == null || currentTransition.HasZeroDuration())
            {
                // Without a transition (or a transition which has no duration), the animations
                // defined in the ToState are supposed to start immediately.
                VisualStateSource.Verbose(
                    "Not using transitions. Transitions available: {0}",
                    currentTransition != null);
                PlayToStateAnimations(currentTransition);
            }
            else
            {
                VisualStateSource.Verbose("Using generated transition storyboard...");
                PlayTransitionAnimations(currentTransition, dynamicTransitionStoryboard);
            }

            return(true);
        }