private static void PrepareSharedTransition(ITransitionMapper tm, Page pageFrom, Page pageTo, bool isPop)
        {
            IReadOnlyList <TransitionDetail> transFrom = null;

            if (isPop)
            {
                // current page is pageFrom being popped; new page will be pageTo

                transFrom = tm.GetMap(pageFrom, null, isPop);
            }
            else
            {
                // current page == pageFrom; new page to push pageTo

                // group is used when pushing from a page with the group defined
                var group = (string)pageFrom?.GetValue(SharedTransitionNavigationPage.TransitionSelectedGroupProperty);

                transFrom = tm.GetMap(pageFrom, group, isPop);
            }

            // save this so that when we return to the page, we don't have to guess which items to use
            pageFrom?.SetValue(SharedTransitionNavigationPage.TransitionFromMapProperty, transFrom);

            var cas = ConnectedAnimationService.GetForCurrentView();

            if (pageFrom != null)
            {
                cas.DefaultDuration = TimeSpan.FromMilliseconds((long)pageFrom.GetValue(SharedTransitionNavigationPage.TransitionDurationProperty));
            }

            // TODO: better indication of Background items to do first...
            foreach (var bg in transFrom.Where(td => td.TransitionName.Contains("Background")))
            {
                if (bg.NativeView.IsAlive)
                {
                    var ca = cas.PrepareToAnimate(bg.TransitionName, (UIElement)bg.NativeView.Target);
                }
            }

            foreach (var detail in transFrom.Where(td => !td.TransitionName.Contains("Background")))
            {
                if (detail.NativeView.IsAlive)
                {
                    var ca = cas.PrepareToAnimate(detail.TransitionName, (UIElement)detail.NativeView.Target);
                }
            }
        }
        private static void ExecutePreparedTransition(ITransitionMapper tm, Page pageFrom, Page pageTo, bool isPop)
        {
            var cas = ConnectedAnimationService.GetForCurrentView();

            var transFrom = (IReadOnlyList <TransitionDetail>)pageFrom?.GetValue(SharedTransitionNavigationPage.TransitionFromMapProperty);

            pageFrom?.SetValue(SharedTransitionNavigationPage.TransitionFromMapProperty, null);

            // group is used when popping back to a page with the group defined
            var group   = (string)pageTo?.GetValue(SharedTransitionNavigationPage.TransitionSelectedGroupProperty);
            var transTo = tm.GetMap(pageTo, group, !isPop);

            foreach (var detail in transTo)
            {
                ConnectedAnimation animation = cas.GetAnimation(detail.TransitionName);
                if (animation != null)
                {
                    if (detail.NativeView.IsAlive)
                    {
                        if (detail.View.Height == -1)
                        {
                            // need to capture the value and then use that in the event handler since it changes with each time through the loop
                            var acapture = animation;
                            detail.View.SizeChanged += (s, e) =>
                            {
                                // save this so we only call TryStart on the first time through
                                var atemp = acapture;
                                acapture = null;
                                if (atemp != null && detail.NativeView.IsAlive)
                                {
                                    atemp.TryStart((UIElement)detail.NativeView.Target);
                                }
                            };
                        }
                        else
                        {
                            var b = animation.TryStart((UIElement)detail.NativeView.Target);
                        }
                    }
                }
            }

            foreach (var transChk in transFrom ?? Enumerable.Empty <TransitionDetail>())
            {
                if (!transTo.Any(t => t.TransitionName == transChk.TransitionName))
                {
                    // transFrom item not in transTo
                    ConnectedAnimation animation = cas.GetAnimation(transChk.TransitionName);
                    if (animation != null)
                    {
                        animation.Cancel();
                    }

                    if (isPop)
                    {
                        // TODO: figure out why this is needed
                        transChk.View.IsVisible = false;
                        if (transChk.NativeView.IsAlive)
                        {
                            ((UIElement)transChk.NativeView.Target).Visibility = Visibility.Collapsed;
                        }
                    }
                }
            }
        }