/// <summary>
        ///     Returns the value margins for a given axis.
        /// </summary>
        /// <param name="consumer">
        ///     The axis to retrieve the value margins for.
        /// </param>
        /// <returns>A sequence of value margins.</returns>
        protected virtual IEnumerable <ValueMargin> GetValueMargins(IValueMarginConsumer consumer)
        {
            var axis = consumer as IAxis;

            if (axis != null && ActiveDataPoints.Any())
            {
                Func <DataPoint, IComparable> selector = null;
                DataPoint minimumPoint = null;
                DataPoint maximumPoint = null;
                double    margin       = 0.0;
                if (axis == InternalActualIndependentAxis)
                {
                    selector = dataPoint => (IComparable)dataPoint.ActualIndependentValue;

                    minimumPoint = ActiveDataPoints.MinOrNull(selector);
                    maximumPoint = ActiveDataPoints.MaxOrNull(selector);
                    margin       = minimumPoint.GetActualMargin(InternalActualIndependentAxis);
                }
                else if (axis == InternalActualDependentAxis)
                {
                    selector = dataPoint => dataPoint.ActualDependentValue;

                    Tuple <DataPoint, DataPoint> largestAndSmallestValues =
                        DataPointsByActualDependentValue.GetLargestAndSmallestValues();
                    minimumPoint = largestAndSmallestValues.Item1;
                    maximumPoint = largestAndSmallestValues.Item2;
                    margin       = minimumPoint.GetActualMargin(InternalActualDependentAxis);
                }

                yield return(new ValueMargin(selector(minimumPoint), margin, margin));

                yield return(new ValueMargin(selector(maximumPoint), margin, margin));
            }
        }
        /// <summary>
        /// Update the axes when the specified data point's ActualDependentValue property changes.
        /// </summary>
        /// <param name="dataPoint">The data point.</param>
        /// <param name="oldValue">The old value.</param>
        /// <param name="newValue">The new value.</param>
        protected override void OnDataPointActualDependentValueChanged(DataPoint dataPoint, IComparable oldValue, IComparable newValue)
        {
            if (oldValue != null)
            {
                bool removed = DataPointsByActualDependentValue.Remove(oldValue, dataPoint);
                if (removed)
                {
                    DataPointsByActualDependentValue.Add(newValue, dataPoint);
                }
            }

            UpdateActualDependentAxis();
            UpdateDataPoint(dataPoint);
            base.OnDataPointActualDependentValueChanged(dataPoint, oldValue, newValue);
        }
        /// <summary>
        /// Called after data points have been loaded from the items source.
        /// </summary>
        /// <param name="newDataPoints">New active data points.</param>
        /// <param name="oldDataPoints">Old inactive data points.</param>
        protected override void OnDataPointsChanged(IList <DataPoint> newDataPoints, IList <DataPoint> oldDataPoints)
        {
            foreach (DataPoint dataPoint in newDataPoints)
            {
                DataPointsByActualDependentValue.Add(dataPoint.ActualDependentValue, dataPoint);
            }

            foreach (DataPoint dataPoint in oldDataPoints)
            {
                DataPointsByActualDependentValue.Remove(dataPoint.ActualDependentValue, dataPoint);
            }

            GetAxes();

            if (InternalActualDependentAxis != null && InternalActualIndependentAxis != null)
            {
                Action action = () =>
                {
                    AxesInvalidated = false;
                    UpdatingAllAxes = true;
                    try
                    {
                        UpdateActualIndependentAxis();
                        UpdateActualDependentAxis();
                    }
                    finally
                    {
                        UpdatingAllAxes = false;
                    }

                    if (AxesInvalidated)
                    {
                        UpdateDataPoints(ActiveDataPoints);
                    }
                    else
                    {
                        UpdateDataPoints(newDataPoints);
                    }

                    AxesInvalidated = false;
                };

                InvokeOnLayoutUpdated(action);
            }

            base.OnDataPointsChanged(newDataPoints, oldDataPoints);
        }
        /// <summary>
        ///     Returns the actual range of data for a given axis.
        /// </summary>
        /// <param name="consumer">The axis to retrieve the range for.</param>
        /// <returns>The actual range of data.</returns>
        protected virtual Range <IComparable> GetRange(IRangeConsumer consumer)
        {
            if (consumer == null)
            {
                throw new ArgumentNullException("consumer");
            }

            if (consumer == InternalActualDependentAxis)
            {
                if (DataPointsByActualDependentValue.Count > 0)
                {
                    return(DataPointsByActualDependentValue.GetKeyRange());
                }
            }

            var axis = consumer as IAxis;

            return((axis != null)
                ? ActiveDataPoints.Select(dataPoint => (IComparable)GetActualDataPointAxisValue(dataPoint, axis))
                   .GetRange()
                : new Range <IComparable>());
        }