/// <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> /// Removes data point's legend item when the data point is removed. /// </summary> /// <param name="dataPoint">The data point to remove.</param> protected override void RemoveDataPoint(DataPoint dataPoint) { base.RemoveDataPoint(dataPoint); if (dataPoint != null) { LegendItem legendItem = _dataPointLegendItems[dataPoint]; _dataPointLegendItems.Remove(dataPoint); LegendItems.Remove(legendItem); UpdateLegendItemIndexes(); } }
/// <summary> /// Handles data point state property change. /// </summary> /// <param name="dataPoint">The data point.</param> /// <param name="oldValue">The old value.</param> /// <param name="newValue">The new value.</param> protected virtual void OnDataPointStateChanged(DataPoint dataPoint, DataPointState oldValue, DataPointState newValue) { if (dataPoint.State == DataPointState.Hidden) { DetachEventHandlersFromDataPoint(dataPoint); PlotArea.Children.Remove(dataPoint); } }
/// <summary> /// Removes a data point from the plot area. /// </summary> /// <param name="dataPoint">The data point to remove.</param> protected virtual void RemoveDataPoint(DataPoint dataPoint) { if (dataPoint.IsSelected) { Unselect(dataPoint); } if (!LoadingDataPoints) { dataPoint.State = DataPointState.Hiding; } else { dataPoint.State = DataPointState.PendingRemoval; } ActiveDataPointCount--; }
/// <summary> /// Adds a data point to the plot area. /// </summary> /// <param name="dataPoint">The data point to add to the plot area. /// </param> protected virtual void AddDataPoint(DataPoint dataPoint) { if (dataPoint.IsSelected) { Select(dataPoint); } if (PlotArea != null) { // Positioning data point outside the visible area. Canvas.SetLeft(dataPoint, float.MinValue); Canvas.SetTop(dataPoint, float.MinValue); dataPoint.IsSelectionEnabled = IsSelectionEnabled; PlotArea.Children.Insert(GetInsertionIndex(dataPoint), dataPoint); ActiveDataPointCount++; if (!LoadingDataPoints) { dataPoint.State = DataPointState.Showing; } } }
/// <summary> /// Returns the index at which to insert data point in the plot area /// child collection. /// </summary> /// <param name="dataPoint">The data point to retrieve the insertion /// index for.</param> /// <returns>The insertion index.</returns> protected virtual int GetInsertionIndex(DataPoint dataPoint) { return PlotArea.Children.Count; }
/// <summary> /// Updates each point. /// </summary> /// <param name="dataPoint">The data point to update.</param> protected override void UpdateDataPoint(DataPoint dataPoint) { if (SeriesHost == null || PlotArea == null) { return; } object category = dataPoint.IndependentValue ?? (this.ActiveDataPoints.IndexOf(dataPoint) + 1); Range<double> coordinateRange = ActualIndependentCategoryAxis.GetPlotAreaCoordinateRange(category); if (!coordinateRange.HasData) { return; } double plotAreaHeight = ActualDependentRangeAxis.GetPlotAreaCoordinate(ActualDependentRangeAxis.Range.Maximum); IEnumerable<ColumnSeries> columnSeries = SeriesHost.Series.OfType<ColumnSeries>().Where(series => series.ActualIndependentCategoryAxis == ActualIndependentCategoryAxis); int numberOfSeries = columnSeries.Count(); double coordinateRangeWidth = (coordinateRange.Maximum - coordinateRange.Minimum); double segmentWidth = coordinateRangeWidth * 0.8; double columnWidth = segmentWidth / numberOfSeries; int seriesIndex = columnSeries.IndexOf(this); double dataPointY = ActualDependentRangeAxis.GetPlotAreaCoordinate(ValueHelper.ToDouble(dataPoint.ActualDependentValue)); double zeroPointY = ActualDependentRangeAxis.GetPlotAreaCoordinate(0); double offset = seriesIndex * Math.Round(columnWidth) + coordinateRangeWidth * 0.1; double dataPointX = coordinateRange.Minimum + offset; if (_categoriesWithMultipleDataPoints.ContainsKey(category)) { // Multiple DataPoints share this category; offset and overlap them appropriately IGrouping<object, DataPoint> categoryGrouping = _categoriesWithMultipleDataPoints[category]; int index = categoryGrouping.IndexOf(dataPoint); dataPointX += (index * (columnWidth * 0.2)) / (categoryGrouping.Count() - 1); columnWidth *= 0.8; Canvas.SetZIndex(dataPoint, -index); } if (!double.IsNaN(dataPointY) && !double.IsNaN(dataPointX) && !double.IsNaN(zeroPointY)) { double left = Math.Round(dataPointX); double width = Math.Round(columnWidth); double top = Math.Round(plotAreaHeight - Math.Max(dataPointY, zeroPointY) + 0.5); double bottom = Math.Round(plotAreaHeight - Math.Min(dataPointY, zeroPointY) + 0.5); double height = bottom - top + 1; Canvas.SetLeft(dataPoint, left); Canvas.SetTop(dataPoint, top); dataPoint.Width = width; dataPoint.Height = height; } }
/// <summary> /// Selects a data point. /// </summary> /// <param name="dataPoint">The data point to select.</param> private void Select(DataPoint dataPoint) { foreach (DataPoint currentDataPoint in ActiveDataPoints.Where(currentDataPoint => currentDataPoint != dataPoint)) { currentDataPoint.IsSelectedChanged -= OnDataPointIsSelectedChanged; currentDataPoint.IsSelected = false; currentDataPoint.IsSelectedChanged += OnDataPointIsSelectedChanged; } SelectedItem = dataPoint.DataContext; }
/// <summary> /// Updates each point. /// </summary> /// <param name="dataPoint">The data point to update.</param> protected override void UpdateDataPoint(DataPoint dataPoint) { if (SeriesHost == null || PlotArea == null) { return; } object category = dataPoint.IndependentValue ?? (this.ActiveDataPoints.IndexOf(dataPoint) + 1); Range<double> coordinateRange = ActualIndependentCategoryAxis.GetPlotAreaCoordinateRange(category); if (!coordinateRange.HasData) { return; } IEnumerable<BarSeries> barSeries = SeriesHost.Series.OfType<BarSeries>().Where(series => series.ActualIndependentCategoryAxis == ActualIndependentCategoryAxis); int numberOfSeries = barSeries.Count(); double coordinateRangeHeight = (coordinateRange.Maximum - coordinateRange.Minimum); double segmentHeight = coordinateRangeHeight * 0.8; double barHeight = segmentHeight / numberOfSeries; int seriesIndex = barSeries.IndexOf(this); double dataPointX = ActualDependentRangeAxis.GetPlotAreaCoordinate(ValueHelper.ToDouble(dataPoint.ActualDependentValue)); double zeroPointX = ActualDependentRangeAxis.GetPlotAreaCoordinate(0); double offset = seriesIndex * Math.Round(barHeight) + coordinateRangeHeight * 0.1; double dataPointY = coordinateRange.Minimum + offset; if (_categoriesWithMultipleDataPoints.ContainsKey(category)) { // Multiple DataPoints share this category; offset and overlap them appropriately IGrouping<object, DataPoint> categoryGrouping = _categoriesWithMultipleDataPoints[category]; int index = categoryGrouping.IndexOf(dataPoint); dataPointY += (index * (barHeight * 0.2)) / (categoryGrouping.Count() - 1); barHeight *= 0.8; Canvas.SetZIndex(dataPoint, -index); } if (ValueHelper.CanGraph(dataPointX) && ValueHelper.CanGraph(dataPointY) && ValueHelper.CanGraph(zeroPointX)) { double top = Math.Round(dataPointY); double height = Math.Round(barHeight); double left = Math.Round(Math.Min(dataPointX, zeroPointX) - 0.5); double right = Math.Round(Math.Max(dataPointX, zeroPointX) - 0.5); double width = right - left + 1; Canvas.SetLeft(dataPoint, left); Canvas.SetTop(dataPoint, top); dataPoint.Width = width; dataPoint.Height = height; } }
/// <summary> /// Updates a data point when its actual dependent value has changed. /// </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, object oldValue, object newValue) { UpdateDataPoint(dataPoint); base.OnDataPointActualDependentValueChanged(dataPoint, oldValue, newValue); }
/// <summary> /// Updates the visual representation of the data point. /// </summary> /// <param name="dataPoint">The data point to update.</param> protected override void UpdateDataPoint(DataPoint dataPoint) { double maximum = ActualDependentRangeAxis.GetPlotAreaCoordinate(ActualDependentRangeAxis.Range.Maximum); if (ValueHelper.CanGraph(maximum)) { double x = ActualIndependentRangeAxis.GetPlotAreaCoordinate(ValueHelper.ToComparable(dataPoint.ActualIndependentValue)); double y = ActualDependentRangeAxis.GetPlotAreaCoordinate(ValueHelper.ToDouble(dataPoint.ActualDependentValue)); if (ValueHelper.CanGraph(x) && ValueHelper.CanGraph(y)) { if (!double.IsNaN(MarkerHeight)) { dataPoint.Height = MarkerHeight; } if (!double.IsNaN(MarkerWidth)) { dataPoint.Width = MarkerWidth; } // Call UpdateLayout to ensure ActualWidth/ActualHeight are correct if (dataPoint.ActualWidth == 0.0 || dataPoint.ActualHeight == 0.0) { dataPoint.UpdateLayout(); } double coordinateY = Math.Round(maximum - (y + (dataPoint.ActualHeight / 2))); Canvas.SetTop(dataPoint, coordinateY); double coordinateX = Math.Round(x - (dataPoint.ActualWidth / 2)); Canvas.SetLeft(dataPoint, coordinateX); } if (!UpdatingAllDataPoints) { UpdatePointsCollection(); } } }
/// <summary> /// Sets the style of the data point to the single style used for all /// data points. /// </summary> /// <param name="dataPoint">The data point to apply the style to. /// </param> /// <param name="dataContext">The object associated with the data point. /// </param> protected override void PrepareDataPoint(DataPoint dataPoint, object dataContext) { if (dataPoint.Style == null) { dataPoint.Style = ActualDataPointStyle; } base.PrepareDataPoint(dataPoint, dataContext); }
/// <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> /// Updates a data point. /// </summary> /// <param name="dataPoint">The data point to update.</param> protected override void UpdateDataPoint(DataPoint dataPoint) { PieDataPoint pieDataPoint = (PieDataPoint) dataPoint; pieDataPoint.Width = ActualWidth; pieDataPoint.Height = ActualHeight; UpdatePieDataPointGeometry(pieDataPoint, ActualWidth, ActualHeight); Canvas.SetLeft(pieDataPoint, 0); Canvas.SetTop(pieDataPoint, 0); }
/// <summary> /// Acquire a horizontal linear axis and a vertical linear axis. /// </summary> /// <param name="firstDataPoint">The first data point.</param> protected override void GetAxes(DataPoint firstDataPoint) { GetRangeAxis( InternalIndependentAxis, firstDataPoint, AxisOrientation.Horizontal, () => CreateRangeAxisFromData(firstDataPoint.IndependentValue), () => InternalActualIndependentAxis as IRangeAxis, (value) => { InternalActualIndependentAxis = (IAxis)value; }, (dataPoint) => dataPoint.IndependentValue); GetRangeAxis( InternalDependentAxis, firstDataPoint, AxisOrientation.Vertical, () => { HybridAxis axis = (HybridAxis) CreateRangeAxisFromData(firstDataPoint.DependentValue); axis.ShowGridLines = true; return (IRangeAxis) axis; }, () => InternalActualDependentAxis as IRangeAxis, (value) => { InternalActualDependentAxis = (IAxis)value; }, (dataPoint) => dataPoint.DependentValue); }
/// <summary> /// Creates a legend item from a data point. /// </summary> /// <param name="dataPoint">The data point to use to create the legend item.</param> /// <param name="index">The 1-based index of the Control.</param> /// <returns>The series host legend item.</returns> private LegendItem CreatePieLegendItem(DataPoint dataPoint, int index) { LegendItem legendItem = CreateLegendItem(); // Set the Content of the LegendItem legendItem.Content = dataPoint.IndependentValue ?? index; // Create a representative DataPoint for access to styled properties DataPoint legendDataPoint = CreateDataPoint(); legendDataPoint.Style = dataPoint.Style; legendItem.DataContext = legendDataPoint; return legendItem; }
/// <summary> /// This method updates a single data point. /// </summary> /// <param name="dataPoint">The data point to update.</param> protected override void UpdateDataPoint(DataPoint dataPoint) { double PlotAreaHeight = ActualDependentRangeAxis.GetPlotAreaCoordinate(ActualDependentRangeAxis.Range.Maximum); double dataPointX = ActualIndependentRangeAxis.GetPlotAreaCoordinate(ValueHelper.ToComparable(dataPoint.ActualIndependentValue)); double dataPointY = ActualDependentRangeAxis.GetPlotAreaCoordinate(ValueHelper.ToDouble(dataPoint.ActualDependentValue)); if (ValueHelper.CanGraph(dataPointX) && ValueHelper.CanGraph(dataPointY)) { // Set dimensions if (!double.IsNaN(MarkerHeight)) { dataPoint.Height = MarkerHeight; } if (!double.IsNaN(MarkerWidth)) { dataPoint.Width = MarkerWidth; } // Call UpdateLayout to ensure ActualWidth/ActualHeight are correct if (dataPoint.ActualWidth == 0.0 || dataPoint.ActualHeight == 0.0) { dataPoint.UpdateLayout(); } // Set the Position Canvas.SetLeft( dataPoint, Math.Round(dataPointX - (dataPoint.ActualWidth / 2))); Canvas.SetTop( dataPoint, Math.Round(PlotAreaHeight - (dataPointY + (dataPoint.ActualHeight / 2)))); } }
/// <summary> /// Unselects a data point. /// </summary> /// <param name="dataPoint">The data point to unselect.</param> private void Unselect(DataPoint dataPoint) { if (dataPoint.DataContext.Equals(SelectedItem)) { SelectedItem = null; } }
/// <summary> /// Creates a legend item for each data point. /// </summary> /// <param name="dataPoint">The data point added.</param> protected override void AddDataPoint(DataPoint dataPoint) { base.AddDataPoint(dataPoint); int index = ActiveDataPoints.IndexOf(dataPoint) + 1; Style style = NextStyle(typeof(PieDataPoint), true); if (dataPoint.Style == null) { dataPoint.Style = style; } LegendItem legendItem = CreatePieLegendItem(dataPoint, index); _dataPointLegendItems[dataPoint] = legendItem; LegendItems.Add(legendItem); UpdateLegendItemIndexes(); }
/// <summary> /// Detaches event handlers from a data point. /// </summary> /// <param name="dataPoint">The data point.</param> protected virtual void DetachEventHandlersFromDataPoint(DataPoint dataPoint) { dataPoint.IsSelectedChanged -= OnDataPointIsSelectedChanged; dataPoint.ActualDependentValueChanged -= OnDataPointActualDependentValueChanged; dataPoint.ActualIndependentValueChanged -= OnDataPointActualIndependentValueChanged; dataPoint.DependentValueChanged -= OnDataPointDependentValueChanged; dataPoint.IndependentValueChanged -= OnDataPointIndependentValueChanged; dataPoint.StateChanged -= OnDataPointStateChanged; }
/// <summary> /// Detaches event handlers from a data point. /// </summary> /// <param name="dataPoint">The data point.</param> protected override void DetachEventHandlersFromDataPoint(DataPoint dataPoint) { PieDataPoint pieDataPoint = dataPoint as PieDataPoint; pieDataPoint.ActualRatioChanged -= OnPieDataPointActualRatioChanged; pieDataPoint.ActualOffsetRatioChanged -= OnPieDataPointActualOffsetRatioChanged; pieDataPoint.RatioChanged -= OnPieDataPointRatioChanged; pieDataPoint.OffsetRatioChanged -= OnPieDataPointOffsetRatioChanged; base.DetachEventHandlersFromDataPoint(dataPoint); }
/// <summary> /// Handles data point independent value property change. /// </summary> /// <param name="dataPoint">The data point.</param> /// <param name="oldValue">The old value.</param> /// <param name="newValue">The new value.</param> protected virtual void OnDataPointIndependentValueChanged(DataPoint dataPoint, object oldValue, object newValue) { }
/// <summary> /// Updates the data point when the dependent value is changed. /// </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 OnDataPointDependentValueChanged(DataPoint dataPoint, object oldValue, object newValue) { UpdateRatios(); base.OnDataPointDependentValueChanged(dataPoint, oldValue, newValue); }
/// <summary> /// Prepares a data point by extracting binding it to a data context /// object. /// </summary> /// <param name="dataPoint">A data point.</param> /// <param name="dataContext">A data context object.</param> protected virtual void PrepareDataPoint(DataPoint dataPoint, object dataContext) { // Create a Control with DataContext set to the data source dataPoint.DataContext = dataContext; // Set bindings for IndependentValue/DependentValue if (IndependentValueBinding != null) { dataPoint.SetBinding(DataPoint.IndependentValueProperty, IndependentValueBinding); } if (DependentValueBinding == null) { dataPoint.SetBinding(DataPoint.DependentValueProperty, new Binding()); } else { dataPoint.SetBinding(DataPoint.DependentValueProperty, DependentValueBinding); } }
/// <summary> /// Updates the data point when the independent value is changed. /// </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 OnDataPointIndependentValueChanged(DataPoint dataPoint, object oldValue, object newValue) { _dataPointLegendItems[dataPoint].Content = newValue; base.OnDataPointIndependentValueChanged(dataPoint, oldValue, newValue); }
/// <summary> /// Updates the visual representation of a single data point in the plot /// area. /// </summary> /// <param name="dataPoint">The data point to update.</param> protected abstract void UpdateDataPoint(DataPoint dataPoint);
/// <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); }