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); } }
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); }