/// <summary>
        /// Zoom in/out centered on the specified point (in content coordinates).
        /// The focus point is kept locked to it's on screen position (ala google maps).
        /// </summary>
        public void AnimatedZoomAboutPoint(double newContentScale, Point contentZoomFocus)
        {
            newContentScale = Math.Min(Math.Max(newContentScale, MinContentScale), MaxContentScale);

            ZoomPanAnimationHelper.CancelAnimation(this, ContentZoomFocusXProperty);
            ZoomPanAnimationHelper.CancelAnimation(this, ContentZoomFocusYProperty);
            ZoomPanAnimationHelper.CancelAnimation(this, ViewportZoomFocusXProperty);
            ZoomPanAnimationHelper.CancelAnimation(this, ViewportZoomFocusYProperty);

            ContentZoomFocusX  = contentZoomFocus.X;
            ContentZoomFocusY  = contentZoomFocus.Y;
            ViewportZoomFocusX = (ContentZoomFocusX - ContentOffsetX) * ContentScale;
            ViewportZoomFocusY = (ContentZoomFocusY - ContentOffsetY) * ContentScale;

            //
            // When zooming about a point make updates to ContentScale also update content offset.
            //
            _enableContentOffsetUpdateFromScale = true;

            ZoomPanAnimationHelper.StartAnimation(this, ContentScaleProperty, newContentScale, AnimationDuration,
                                                  delegate(object sender, EventArgs e)
            {
                _enableContentOffsetUpdateFromScale = false;

                ResetViewportZoomFocus();
            });
        }
        /// <summary>
        /// Zoom to the specified scale and move the specified focus point to the center of the viewport.
        /// </summary>
        private void AnimatedZoomPointToViewportCenter(double newContentScale, Point contentZoomFocus, EventHandler callback)
        {
            newContentScale = Math.Min(Math.Max(newContentScale, MinContentScale), MaxContentScale);

            ZoomPanAnimationHelper.CancelAnimation(this, ContentZoomFocusXProperty);
            ZoomPanAnimationHelper.CancelAnimation(this, ContentZoomFocusYProperty);
            ZoomPanAnimationHelper.CancelAnimation(this, ViewportZoomFocusXProperty);
            ZoomPanAnimationHelper.CancelAnimation(this, ViewportZoomFocusYProperty);

            ContentZoomFocusX  = contentZoomFocus.X;
            ContentZoomFocusY  = contentZoomFocus.Y;
            ViewportZoomFocusX = (ContentZoomFocusX - ContentOffsetX) * ContentScale;
            ViewportZoomFocusY = (ContentZoomFocusY - ContentOffsetY) * ContentScale;

            //
            // When zooming about a point make updates to ContentScale also update content offset.
            //
            _enableContentOffsetUpdateFromScale = true;

            ZoomPanAnimationHelper.StartAnimation(this, ContentScaleProperty, newContentScale, AnimationDuration,
                                                  delegate(object sender, EventArgs e)
            {
                _enableContentOffsetUpdateFromScale = false;

                if (callback != null)
                {
                    callback(this, EventArgs.Empty);
                }
            });

            ZoomPanAnimationHelper.StartAnimation(this, ViewportZoomFocusXProperty, ViewportWidth / 2, AnimationDuration);
            ZoomPanAnimationHelper.StartAnimation(this, ViewportZoomFocusYProperty, ViewportHeight / 2, AnimationDuration);
        }
        /// <summary>
        /// Use animation to center the view on the specified point (in content coordinates).
        /// </summary>
        public void AnimatedSnapTo(Point contentPoint)
        {
            double newX = contentPoint.X - (this.ContentViewportWidth / 2);
            double newY = contentPoint.Y - (this.ContentViewportHeight / 2);

            ZoomPanAnimationHelper.StartAnimation(this, ContentOffsetXProperty, newX, AnimationDuration);
            ZoomPanAnimationHelper.StartAnimation(this, ContentOffsetYProperty, newY, AnimationDuration);
        }