protected override Range <IComparable> IRangeProviderGetRange(IRangeConsumer rangeConsumer) { if (rangeConsumer == ActualDependentAxis) { var dependentValuesByIndependentValue = IndependentValueDependentValues.Select(e => e.ToArray()).ToArray(); var mostNegative = dependentValuesByIndependentValue .Select(g => g.Where(v => v < 0) .Sum()) .Where(v => v < 0) .ToArray(); var leastNegative = dependentValuesByIndependentValue .Select(g => g.Where(v => v <= 0) .DefaultIfEmpty(1.0) .First()) .Where(v => v <= 0) .ToArray(); var mostPositive = dependentValuesByIndependentValue .Select(g => g.Where(v => 0 < v) .Sum()) .Where(v => 0 < v) .ToArray(); var leastPositive = dependentValuesByIndependentValue .Select(g => g.Where(v => 0 <= v) .DefaultIfEmpty(-1.0) .First()) .Where(v => 0 <= v) .ToArray(); // Compute minimum double minimum = 0; if (mostNegative.Any()) { minimum = mostNegative.Min(); } else if (leastPositive.Any()) { minimum = leastPositive.Min(); } // Compute maximum double maximum = 0; if (mostPositive.Any()) { maximum = mostPositive.Max(); } else if (leastNegative.Any()) { maximum = leastNegative.Max(); } if (IsStacked100) { minimum = Math.Min(minimum, 0); maximum = Math.Max(maximum, 0); } return(new Range <IComparable>(minimum, maximum)); } else if (rangeConsumer == ActualIndependentAxis) { // Using a non-ICategoryAxis for the independent axis // Need to specifically adjust for slot size of bars/columns so they don't overlap // Note: Calculation for slotSize is not perfect, but it's quick, close, and errs on the safe side Range <IComparable> range = base.IRangeProviderGetRange(rangeConsumer); int count = Math.Max(IndependentValueGroups.Count(), 1); if (ActualIndependentAxis.CanPlot(0.0)) { double minimum = ValueHelper.ToDouble(range.Minimum); double maximum = ValueHelper.ToDouble(range.Maximum); double slotSize = (maximum - minimum) / count; return(new Range <IComparable>(minimum - slotSize, maximum + slotSize)); } else { DateTime minimum = ValueHelper.ToDateTime(range.Minimum); DateTime maximum = ValueHelper.ToDateTime(range.Maximum); TimeSpan slotSize = TimeSpan.FromTicks((maximum - minimum).Ticks / count); return(new Range <IComparable>(minimum - slotSize, maximum + slotSize)); } } else { return(base.IRangeProviderGetRange(rangeConsumer)); } }
protected override void UpdateDataItemPlacement(IEnumerable <DefinitionSeries.DataItem> dataItems) { IAxis actualIndependentAxis = ActualIndependentAxis; if ((null != ActualDependentAxis) && (null != actualIndependentAxis)) { double plotAreaMaximumDependentCoordinate = ActualDependentAxis.GetPlotAreaCoordinate(ActualDependentRangeAxis.Range.Maximum).Value; double zeroCoordinate = ActualDependentAxis.GetPlotAreaCoordinate(ActualDependentRangeAxis.Origin ?? 0.0).Value; ICategoryAxis actualIndependentCategoryAxis = actualIndependentAxis as ICategoryAxis; double nonCategoryAxisRangeMargin = (null != actualIndependentCategoryAxis) ? 0 : GetMarginForNonCategoryAxis(actualIndependentAxis); foreach (IndependentValueGroup group in IndependentValueGroups) { Range <UnitValue> categoryRange = new Range <UnitValue>(); if (null != actualIndependentCategoryAxis) { categoryRange = actualIndependentCategoryAxis.GetPlotAreaCoordinateRange(group.IndependentValue); } else { UnitValue independentValueCoordinate = actualIndependentAxis.GetPlotAreaCoordinate(group.IndependentValue); if (ValueHelper.CanGraph(independentValueCoordinate.Value)) { categoryRange = new Range <UnitValue>(new UnitValue(independentValueCoordinate.Value - nonCategoryAxisRangeMargin, independentValueCoordinate.Unit), new UnitValue(independentValueCoordinate.Value + nonCategoryAxisRangeMargin, independentValueCoordinate.Unit)); } } if (categoryRange.HasData) { double categoryMinimumCoordinate = categoryRange.Minimum.Value; double categoryMaximumCoordinate = categoryRange.Maximum.Value; double padding = 0.1 * (categoryMaximumCoordinate - categoryMinimumCoordinate); categoryMinimumCoordinate += padding; categoryMaximumCoordinate -= padding; double sum = IsStacked100 ? group.DataItems.Sum(di => Math.Abs(ValueHelper.ToDouble(di.DataPoint.ActualDependentValue))) : 1; if (0 == sum) { sum = 1; } double ceiling = 0; double floor = 0; foreach (DataItem dataItem in group.DataItems) { DataPoint dataPoint = dataItem.DataPoint; double value = IsStacked100 ? (ValueHelper.ToDouble(dataPoint.ActualDependentValue) * (100 / sum)) : ValueHelper.ToDouble(dataPoint.ActualDependentValue); if (ValueHelper.CanGraph(value)) { double valueCoordinate = ActualDependentAxis.GetPlotAreaCoordinate(value).Value; double fillerCoordinate = (0 <= value) ? ceiling : floor; double topCoordinate = 0, leftCoordinate = 0, height = 0, width = 0, deltaCoordinate = 0; if (AxisOrientation.Y == ActualDependentAxis.Orientation) { topCoordinate = plotAreaMaximumDependentCoordinate - Math.Max(valueCoordinate + fillerCoordinate, zeroCoordinate + fillerCoordinate); double bottomCoordinate = plotAreaMaximumDependentCoordinate - Math.Min(valueCoordinate + fillerCoordinate, zeroCoordinate + fillerCoordinate); deltaCoordinate = bottomCoordinate - topCoordinate; height = (0 < deltaCoordinate) ? deltaCoordinate + 1 : 0; leftCoordinate = categoryMinimumCoordinate; width = categoryMaximumCoordinate - categoryMinimumCoordinate + 1; } else { leftCoordinate = Math.Min(valueCoordinate + fillerCoordinate, zeroCoordinate + fillerCoordinate); double rightCoordinate = Math.Max(valueCoordinate + fillerCoordinate, zeroCoordinate + fillerCoordinate); deltaCoordinate = rightCoordinate - leftCoordinate; width = (0 < deltaCoordinate) ? deltaCoordinate + 1 : 0; topCoordinate = categoryMinimumCoordinate; height = categoryMaximumCoordinate - categoryMinimumCoordinate + 1; } double roundedTopCoordinate = Math.Round(topCoordinate); Canvas.SetTop(dataItem.Container, roundedTopCoordinate); dataPoint.Height = Math.Round(topCoordinate + height - roundedTopCoordinate); double roundedLeftCoordinate = Math.Round(leftCoordinate); Canvas.SetLeft(dataItem.Container, roundedLeftCoordinate); dataPoint.Width = Math.Round(leftCoordinate + width - roundedLeftCoordinate); dataPoint.Visibility = Visibility.Visible; if (0 <= value) { ceiling += deltaCoordinate; } else { floor -= deltaCoordinate; } } else { dataPoint.Visibility = Visibility.Collapsed; } } } else { foreach (DataPoint dataPoint in group.DataItems.Select(di => di.DataPoint)) { dataPoint.Visibility = Visibility.Collapsed; } } } } }