/// <summary>
        /// Updates the data point's visual representation.
        /// </summary>
        /// <param name="dataPoint">The data point.</param>
        protected override void UpdateDataPoint(DataPoint dataPoint)
        {
            double maximumDiameter = Math.Min(PlotAreaSize.Width, PlotAreaSize.Height) * MaximumBubbleSizeAsRatioOfSmallestDimension;

            BubbleDataPoint bubbleDataPoint = (BubbleDataPoint)dataPoint;

            double ratioOfLargestBubble =
                (MaxOfDataPointActualSizeValues.HasValue && MaxOfDataPointActualSizeValues.Value != 0.0 && bubbleDataPoint.ActualSize >= 0.0) ? Math.Abs(bubbleDataPoint.ActualSize) / MaxOfDataPointActualSizeValues.Value : 0.0;

            bubbleDataPoint.Width  = ratioOfLargestBubble * maximumDiameter;
            bubbleDataPoint.Height = ratioOfLargestBubble * maximumDiameter;

            // Call UpdateLayout to ensure ActualWidth/ActualHeight are correct
            if (bubbleDataPoint.ActualWidth == 0.0 || bubbleDataPoint.ActualHeight == 0.0)
            {
                bubbleDataPoint.UpdateLayout();
            }

            double left =
                (ActualIndependentRangeAxis.GetPlotAreaCoordinate((IComparable)bubbleDataPoint.ActualIndependentValue))
                - (bubbleDataPoint.Width / 2.0);

            double top =
                (PlotAreaSize.Height
                 - (bubbleDataPoint.Height / 2.0))
                - ActualDependentRangeAxis.GetPlotAreaCoordinate((IComparable)bubbleDataPoint.ActualDependentValue);

            if (ValueHelper.CanGraph(left) && ValueHelper.CanGraph(top))
            {
                Canvas.SetLeft(bubbleDataPoint, left);
                Canvas.SetTop(bubbleDataPoint, top);
            }
        }
        /// <summary>
        /// Prepares a bubble data point by binding the size value binding to
        /// the size property.
        /// </summary>
        /// <param name="dataPoint">The data point to prepare.</param>
        /// <param name="dataContext">The data context of the data point.
        /// </param>
        protected override void PrepareDataPoint(DataPoint dataPoint, object dataContext)
        {
            base.PrepareDataPoint(dataPoint, dataContext);

            BubbleDataPoint bubbleDataPoint = (BubbleDataPoint)dataPoint;

            bubbleDataPoint.SetBinding(BubbleDataPoint.SizeProperty, SizeValueBinding ?? DependentValueBinding ?? IndependentValueBinding);
        }
        /// <summary>
        /// Detaches size change and actual size change event handlers from the
        /// data point.
        /// </summary>
        /// <param name="dataPoint">The data point.</param>
        protected override void DetachEventHandlersFromDataPoint(DataPoint dataPoint)
        {
            BubbleDataPoint bubbleDataPoint = (BubbleDataPoint)dataPoint;

            bubbleDataPoint.SizePropertyChanged       -= new RoutedPropertyChangedEventHandler <double>(BubbleDataPointSizePropertyChanged);
            bubbleDataPoint.ActualSizePropertyChanged -= new RoutedPropertyChangedEventHandler <double>(BubbleDataPointActualSizePropertyChanged);
            base.DetachEventHandlersFromDataPoint(dataPoint);
        }
        /// <summary>
        /// SizeProperty property changed handler.
        /// </summary>
        /// <param name="d">BubbleDataPoint that changed its Size.</param>
        /// <param name="e">Event arguments.</param>
        private static void OnSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            BubbleDataPoint source   = (BubbleDataPoint)d;
            double          oldValue = (double)e.OldValue;
            double          newValue = (double)e.NewValue;

            source.OnSizePropertyChanged(oldValue, newValue);
        }
        /// <summary>
        /// Animates the value of the ActualSize property to the size property
        /// when it changes.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">Information about the event.</param>
        private void BubbleDataPointSizePropertyChanged(object sender, RoutedPropertyChangedEventArgs <double> e)
        {
            BubbleDataPoint dataPoint = (BubbleDataPoint)sender;

            DependencyPropertyAnimationHelper.BeginAnimation(
                dataPoint,
                BubbleDataPoint.ActualSizeProperty,
                "ActualSize",
                e.NewValue,
                TransitionDuration);
        }