/// <summary>
        /// Fired when one of the lists are scrolling to the bottom.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void List_OnListEndDetectedEvent(object sender, OnListEndDetected e)
        {
            // NOTE!!!
            // This is a very hot code path, so anything done here should be really quick!

            // Get the post
            Post post = ((Post)((FrameworkElement)sender).DataContext);

            // Make sure the margin is normal.
            if(post.FlipViewStickyHeaderMargin.Top != 0)
            {
                // If the margin is not 0 we are playing our render tick. If the sticky header
                // is always set to collapsed it actually never loads or render until we set it to
                // visible while we are scrolling which makes it 'pop' in with a delay. To avoid this
                // it defaults visible but way off the screen, this makes it load and render so it is ready
                // when we set it visible. Here is is safe to restore it to the normal state.
                post.FlipViewStickyHeaderVis = Visibility.Collapsed;
                post.FlipViewStickyHeaderMargin = new Thickness(0, 0, 0, 0);
            }

            // Show or hide the scroll bar depending if we have gotten to comments yet or not.
            post.VerticalScrollBarVisibility = e.ListScrollTotalDistance > 60 ? ScrollBarVisibility.Auto : ScrollBarVisibility.Hidden;

            // Find the header size for this post
            int currentScrollAera = GetCurrentScrollArea(post);

            // This will return -1 if we can't get this yet, so just get out of here.
            if(currentScrollAera == -1)
            {
                return;
            }

            // Get the height of the current post header
            double currentPostHeaderSize = 0;
            lock (m_flipViewStoryHeaders)
            {
                foreach (Grid flipHeader in m_flipViewStoryHeaders)
                {
                    Post headerPost = (Post)(flipHeader.DataContext);
                    if (headerPost != null && headerPost.Id.Equals(post.Id))
                    {
                        currentPostHeaderSize = flipHeader.ActualHeight;
                        break;
                    }
                }
            }

            // Use the header size and the control size to figure out if we should show the static header.
            bool showHeader = e.ListScrollTotalDistance > currentScrollAera - currentPostHeaderSize;
            post.FlipViewStickyHeaderVis = showHeader ? Visibility.Visible : Visibility.Collapsed;

            // If we have a differed header update and we are near the top (not showing the header)
            // do the update now. For a full story see the comment on m_hasDeferredHeaderSizeUpdate
            if (m_hasDeferredHeaderSizeUpdate && !showHeader)
            {
                SetHeaderSizes();
            }

            // Update the last known scroll pos
            m_lastKnownScrollOffset = (int)e.ListScrollTotalDistance;

            // Hide the tip box if needed.
            HideCommentScrollTipIfNeeded();

            // Do the rest of this work on a background thread
            Task.Run(() =>
            {
                FlipViewPostCommentManager manager = null;

                // Get the comment manager for this post
                lock (m_commentManagers)
                {
                    foreach (FlipViewPostCommentManager search in m_commentManagers)
                    {
                        if (search.Post.Id.Equals(post.Id))
                        {
                            // When found, request more posts
                            manager = search;
                            break;
                        }
                    }
                }

                // Make the call if we found one
                if(manager != null)
                {
                    manager.RequestMorePosts();
                }
            });
        }
        /// <summary>
        /// Fired when one of the lists are scrolling to the bottom.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void List_OnListEndDetectedEvent(object sender, OnListEndDetected e)
        {
            // NOTE!!!
            // This is a very hot code path, so anything done here should be really quick!

            // Get the post
            Post post = ((Post)((FrameworkElement)sender).DataContext);

            // Show or hide the scroll bar depending if we have gotten to comments yet or not.
            post.VerticalScrollBarVisibility = e.ListScrollTotalDistance > 60 ? ScrollBarVisibility.Auto : ScrollBarVisibility.Hidden;

            // Find the header size for this post
            int currentScrollAera = GetCurrentScrollArea(post);

            // Get the height of the current post header
            double currentPostHeaderSize = 0;
            lock (m_flipViewStoryHeaders)
            {
                foreach (Grid flipHeader in m_flipViewStoryHeaders)
                {
                    Post headerPost = (Post)(flipHeader.DataContext);
                    if (headerPost != null && headerPost.Id.Equals(post.Id))
                    {
                        currentPostHeaderSize = flipHeader.ActualHeight;
                        break;
                    }
                }
            }

            // Use the header size and the control size to figure out if we should show the static header.
            bool showHeader = e.ListScrollTotalDistance > currentScrollAera - currentPostHeaderSize;
            post.FlipViewStickyHeaderVis = showHeader ? Visibility.Visible : Visibility.Collapsed;

            // If we have a differed header update and we are near the top (not showing the header)
            // do the update now. For a full story see the comment on m_hasDeferredHeaderSizeUpdate
            if (m_hasDeferredHeaderSizeUpdate && !showHeader)
            {
                SetHeaderSizes();
            }

            // Update the last known scroll pos
            m_lastKnownScrollOffset = (int)e.ListScrollTotalDistance;

            // Hide the tip box if needed.
            HideCommentScrollTipIfNeeded();

            // Do the rest of this work on a background thread
            Task.Run(() =>
            {
                // Get the comment manager for this post
                lock (m_commentManagers)
                {
                    foreach (FlipViewPostCommentManager manager in m_commentManagers)
                    {
                        if (manager.Post.Id.Equals(post.Id))
                        {
                            // When found, request more posts
                            manager.RequestMorePosts();
                            break;
                        }
                    }
                }
            });
        }
        /// <summary>
        /// Fired when one of the lists are scrolling to the bottom.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void List_OnListEndDetectedEvent(object sender, OnListEndDetected e)
        {
            // NOTE!!!
            // This is a very hot code path, so anything done here should be really quick!

            FlipViewPostContext context = GetContext();
            if(context == null)
            {
                return;
            }

            // Make sure the margin is normal.
            if (ui_stickyHeader.Margin.Top != 0)
            {
                // If the margin is not 0 we are playing our render tick. If the sticky header
                // is always set to collapsed it actually never loads or render until we set it to
                // visible while we are scrolling which makes it 'pop' in with a delay. To avoid this
                // it defaults visible but way off the screen, this makes it load and render so it is ready
                // when we set it visible. Here is is safe to restore it to the normal state.
                ui_stickyHeader.Visibility = Visibility.Collapsed;
                ui_stickyHeader.Margin = new Thickness(0, 0, 0, 0);
            }

            // Show or hide the scroll bar depending if we have gotten to comments yet or not.
            ScrollViewer.SetVerticalScrollBarVisibility(ui_listView, e.ListScrollTotalDistance > 60 ? ScrollBarVisibility.Auto : ScrollBarVisibility.Hidden);

            // Find the header size for this post
            int currentScrollAera = GetCurrentScrollArea();

            // This will return -1 if we can't get this yet, so just get out of here.
            if (currentScrollAera == -1)
            {
                return;
            }

            // Use the header size and the control size to figure out if we should show the static header.
            bool showHeader = e.ListScrollTotalDistance > currentScrollAera - ui_stickyHeader.ActualHeight;
            ui_stickyHeader.Visibility = showHeader ? Visibility.Visible : Visibility.Collapsed;

            // Get the distance for the animation header to move. We need to account for the header
            // size here because when we move from full screen to not it will toggle. This is very touchy, we 
            // also only want to do this logic if we are scrolling down. On the way back up we need to unminimize 
            // (if the user forced us to be mini) before we hit the real header or things will be wack.
            int headerAniamtionDistance = currentScrollAera;
            if(m_isFullscreen && e.ScrollDirection != ScrollDirection.Up)
            {
                Grid headerGrid = (Grid)m_storyHeader.FindName("ui_storyHeaderBlock");
                headerAniamtionDistance -= (int)headerGrid.ActualHeight;
            }

            // If we are far enough to also hide the header consider hiding it.
            if (e.ListScrollTotalDistance > headerAniamtionDistance)
            {
                if (App.BaconMan.UiSettingsMan.FlipView_MinimizeStoryHeader)
                {
                    if (e.ScrollDirection == ScrollDirection.Down)
                    {
                        ToggleFullscreen(true);
                    }
                    else if(e.ScrollDirection == ScrollDirection.Up)
                    {
                        ToggleFullscreen(false);
                    }
                }
            }
            else
            {
                // If we are the top force it.
                ToggleFullscreen(false, true);
            }


            // If we have a differed header update and we are near the top (not showing the header)
            // do the update now. For a full story see the comment on m_hasDeferredHeaderSizeUpdate
            if (currentScrollAera != context.HeaderSize && context.HeaderSize + 80 > e.ListScrollTotalDistance && e.ScrollDirection == ScrollDirection.Up)
            {
                SetHeaderSize();
            }

            //// Update the last known scroll pos
            m_lastKnownScrollOffset = (int)e.ListScrollTotalDistance;

            //// Hide the tip box if needed.
            HideCommentScrollTipIfNeeded();

            // If we have a manager request more posts.
            if (m_commentManager != null)
            {
                if (m_commentManager.IsOnlyShowingSubset())
                {
                    m_commentManager.RequestMorePosts();
                }
            }
        }