예제 #1
0
        /// <summary>
        /// Transitions into the state. Calls to <see cref="TransitionIn"/> and <see cref="TransitionOut"/> are synchronized
        /// and only one will be executed at a time, the rest will be blocked and executed in FIFO order.
        /// </summary>
        /// <paramref name="useTransitions">If true, use defined storyboard animations in the transition</paramref>
        public override async Task TransitionIn(VisualTransitionType type, bool useTransitions = true)
        {
            // If it's a transition to self and the transition in should be omitted return
            if (type == VisualTransitionType.ToTheSameSetup &&
                !(await GetRepeatedTransition()).HasFlag(RepeatedTransitionBehavior.TransitionIn))
            {
                return;
            }

            // Get into the semaphore
            await _TransitionSemaphore.WaitAsync();

            if (useTransitions)
            {
                bool sbDefined = false;

                // Get on the UI thread
                await DispatcherHelpers.RunAsync(() =>
                {
                    // If the storyboard is defined
                    if (TransitionInStoryboard.WillComplete())
                    {
                        sbDefined = true;

                        // Run it
                        TransitionInStoryboard?.Begin();
                    }
                });

                // If the UI thread task determined that storyboard was defined, start a task that will wait for the storyboard to finish
                if (sbDefined)
                {
                    await Task.Run(() => _WaitForStoryboardToFinish.WaitOne());
                }
            }

            // After the storyboard finished apply the setters
            DispatcherHelpers.RunAsync(() =>
            {
                TemporarySetters?.ForEach((x) => x.Set());
                Setters?.ForEach((x) => x.Set());
            });

            // Transition finished; Release the semaphore
            _TransitionSemaphore.Release();
        }
예제 #2
0
        /// <summary>
        /// Transitions into the state. Cancels transition out operation (if it was happening).
        /// </summary>
        /// <param name="useTransitions"></param>
        /// <returns></returns>
        public override async Task TransitionIn(VisualTransitionType type, bool useTransitions = true)
        {
            // If there's already a transition in going on and we're not supposed to restart it, just return
            if (type == VisualTransitionType.ToTheSameSetup &&
                !(await GetRepeatedTransition()).HasFlag(RepeatedTransitionBehavior.TransitionIn))
            {
                return;
            }

            // If the CancellationTokenSource from the previous transition call is still alive cancel it
            _Cancellation?.Cancel();

            // Create a new source for ourselves
            var cancellation = new CancellationTokenSource();

            // And assign it to the class-wide variable
            _Cancellation = cancellation;

            if (useTransitions)
            {
                bool sbDefined = false;

                // Get on the UI thread
                await DispatcherHelpers.RunAsync(() =>
                {
                    // If the storyboard is defined
                    if (TransitionInStoryboard.WillComplete())
                    {
                        // Mark it for the rest of the Task
                        sbDefined = true;

                        // Pause the transition out storyboard
                        TransitionOutStoryboard?.Pause();
                        // Run the transition in storyboard
                        TransitionInStoryboard?.Begin();
                    }
                });

                // If the UI thread task determined that storyboard was defined,
                // start a task that will wait for the storyboard to finish
                if (sbDefined)
                {
                    // Wait for either for the storyboard to finish or for the CancellationTokenSource to be cancelled
                    // and if the storyboard finished first apply the setters on UI thread
                    //if (WaitHandle.WaitAny(new[] { cancellation.Token.WaitHandle, _WaitForStoryboard }) == 1)
                    if (await Task.Run(() => WaitHandle.WaitAny(new[] { cancellation.Token.WaitHandle, _WaitForStoryboard }) == 1))
                    {
                        // If we weren't cancelled remove the reference to the _Cancellation, otherwise the one cancelling
                        // will provide their own CancellationTokenSource therefore removing the reference to ours
                        _Cancellation = null;
                    }
                }
                else if (!cancellation.IsCancellationRequested)
                {
                    // If our cancellation was not removed by another call, remove the reference to it
                    _Cancellation = null;
                }

                // Apply the setters
                DispatcherHelpers.RunAsync(() =>
                {
                    TemporarySetters?.ForEach((x) => x.Set());
                    Setters?.ForEach((x) => x.Set());
                });
            }

            cancellation.Dispose();
        }