I am creating a User Control component of type DataVisualization.Chart. Currently, it accepts 4 ranges (1 minimum value of the received value and 1 maximum, as well as 1 minimum value of the warning range and 1 maximum value of the warning range). So far, so good. It is working. But I need to add a TextBlock (or a shortcut, or TextBox, whatever) at the end of the LineSeries.
This is my actual LineSeries:

Now I need to do something like this:

Even if the result is not the same, I need to put a label or text block at the end of each LineDataPoint.
Change 1:
This is how my list of items is generated:
/// <summary> /// Generate ItemsSource to use with chart component /// </summary> /// <returns>A observable collection items of ChartItems type</returns> public ObservableCollection<ChartItems> GenerateActualValues() { var itemsSource = ItemsSource as IEnumerable; if (itemsSource.IsNull()) return null; // Get all values from ItemsSource to set Axis Y of Chart List<Double> listAxisY = new List<Double>(); ObservableCollection<ChartItems> chartItems = new ObservableCollection<ChartItems>(); foreach (ChartItems itemSource in itemsSource) { listAxisY.Add(itemSource.ValueY); chartItems.Add(new ChartItems { Name = itemSource.Name, ValueY = itemSource.ValueY, ValueXDouble = itemSource.ValueXDouble, ValueXDateTime = itemSource.ValueXDateTime, Color = itemSource.Color }); } // Set minimum and maximum axis Y if automatic if (AutomaticAxisY) { Double? maxValue; Double? minValue; if (listAxisY.Count > 0) { if (GetMaxLimitValue1(this) > listAxisY.Max()) maxValue = GetMaxLimitValue1(this); else maxValue = listAxisY.Max(); if (GetMinLimitValue1(this) < listAxisY.Min()) minValue = GetMinLimitValue1(this); else minValue = listAxisY.Min(); } else { maxValue = GetMaxLimitValue1(this); minValue = GetMinLimitValue1(this); } Double? increment = (maxValue - minValue) * 0.05; MaximumAxisY = (maxValue + increment).ConvertNullDoubleToDouble(); MinimumAxisY = (minValue - increment).ConvertNullDoubleToDouble(); if (MaximumAxisY == MinimumAxisY) { MaximumAxisY += 1; MinimumAxisY -= 1; } } return chartItems; }
Basically, it generates a new ItemSource for use in my schedule. Now, to generate these additional lines:
/// <summary> /// Generate a ItemsSource using param option informed /// </summary> /// <param name="option">Min1, Max1, Min2, Max2 or Target Value</param> /// <returns>Observable Collection of ChartItems</returns> public ObservableCollection<ChartItems> GenerateLimitValues(String option) { var itemsSource = ItemsSource as IEnumerable; if (itemsSource.IsNull()) return null; Double? valueY = 0.0; ObservableCollection<ChartItems> chartItems = new ObservableCollection<ChartItems>(); switch (option) { case "Min1": valueY = GetMinLimitValue1(this); break; case "Max1": valueY = GetMaxLimitValue1(this); break; case "Target": valueY = GetTargetValue(this); break; case "Min2": valueY = GetMinLimitValue2(this); break; case "Max2": valueY = GetMaxLimitValue2(this); break; } foreach (ChartItems itemSource in itemsSource) chartItems.Add(new ChartItems { Name = itemSource.Name, ValueY = valueY.ConvertNullDoubleToDouble(), ValueXDouble = itemSource.ValueXDouble, ValueXDateTime = itemSource.ValueXDateTime }); return chartItems; }
Now that all things work in my diagram:
/// <summary> /// Generates series with values for chart /// </summary> public void RenderizeChart() { while (this.chartView.Series.Count() - 1 >= 0) this.chartView.Series.Remove(this.chartView.Series[0]); DataPointSeries lineSeriesActualValue = null; DataPointSeries lineSeriesMaxValue1 = null; DataPointSeries lineSeriesMinValue1 = null; DataPointSeries lineSeriesMaxValue2 = null; DataPointSeries lineSeriesMinValue2 = null; DataPointSeries lineSeriesTarget = null; if (!ChartTypeSelectedItem.IsNull()) switch ((ChartTypes)ChartTypeSelectedItem) { case ChartTypes.Bar: this.chartView.Series.Add(new BarSeries()); lineSeriesActualValue = this.chartView.Series[0] as BarSeries; break; case ChartTypes.Columns: this.chartView.Series.Add(new ColumnSeries()); lineSeriesActualValue = this.chartView.Series[0] as ColumnSeries; lineSeriesActualValue.DataPointStyle = (Style)this.Resources["ColumnDataPointStyle"]; break; case ChartTypes.Pie: this.chartView.Series.Add(new PieSeries()); lineSeriesActualValue = this.chartView.Series[0] as PieSeries; break; case ChartTypes.Lines: this.chartView.Series.Add(new LineSeries()); lineSeriesActualValue = this.chartView.Series[0] as LineSeries; lineSeriesActualValue.Style = (Style)this.Resources["LineSeriesStyle"]; if (!ShowPoints) { // Brief explanation: if user wants to hide Data Points, it necessary to get all Setters on // LineDataPointStyle inside xaml, clear previous style and add new Setter. // Otherwise, it will not work, will deny changes because its sealed. Style style = (Style)this.Resources["LineDataPointStyle"]; List<Setter> setterList = new List<Setter>(); foreach (Setter setter in style.Setters) setterList.Add(setter); style = new Style(); foreach (var setter in setterList) style.Setters.Add(setter); style.Setters.Add(new Setter(LineSeries.TemplateProperty, null)); lineSeriesActualValue.DataPointStyle = style; } else lineSeriesActualValue.DataPointStyle = (Style)this.Resources["LineDataPointStyle"]; break; case ChartTypes.Area: this.chartView.Series.Add(new AreaSeries()); lineSeriesActualValue = this.chartView.Series[0] as AreaSeries; break; default: break; } if (!lineSeriesActualValue.IsNull()) { lineSeriesActualValue.IsSelectionEnabled = true; lineSeriesActualValue.DependentValuePath = FieldForDependentValue; lineSeriesActualValue.IndependentValuePath = FieldForIndependentValue; lineSeriesActualValue.ItemsSource = GenerateActualValues(); // Adding a max limit to chart if (!ItemsSource.IsNull() && ((!GetMaxLimitValue1(this).IsNull()) && !GetMaxLimitValue1(this).Equals(0.0))) { this.chartView.Series.Add(new LineSeries()); lineSeriesMaxValue1 = this.chartView.Series[1] as LineSeries; Style styleMaxLineSeries = new Style(); styleMaxLineSeries.Setters.Add(new Setter(LineSeries.BackgroundProperty, new SolidColorBrush(Color.FromArgb(255, 234, 178, 15)))); styleMaxLineSeries.Setters.Add(new Setter(LineSeries.TemplateProperty, null)); lineSeriesMaxValue1.DataPointStyle = styleMaxLineSeries; lineSeriesMaxValue1.DependentValuePath = FieldForDependentValue; lineSeriesMaxValue1.IndependentValuePath = FieldForIndependentValue; lineSeriesMaxValue1.ItemsSource = GenerateLimitValues("Max1"); if (this.chartView.Series.Contains(lineSeriesMaxValue1)) this.chartView.Series.Remove(lineSeriesMaxValue1); this.chartView.Series.Add(lineSeriesMaxValue1); } // Adding a min limit to chart if (!ItemsSource.IsNull() && ((!GetMinLimitValue1(this).IsNull()) && !GetMinLimitValue1(this).Equals(0.0))) { this.chartView.Series.Add(new LineSeries()); lineSeriesMinValue1 = this.chartView.Series[2] as LineSeries; Style styleMinLineSeries = new Style(); styleMinLineSeries.Setters.Add(new Setter(LineSeries.BackgroundProperty, new SolidColorBrush(Color.FromArgb(255, 234, 178, 15)))); styleMinLineSeries.Setters.Add(new Setter(LineSeries.TemplateProperty, null)); lineSeriesMinValue1.DataPointStyle = styleMinLineSeries; lineSeriesMinValue1.DependentValuePath = FieldForDependentValue; lineSeriesMinValue1.IndependentValuePath = FieldForIndependentValue; lineSeriesMinValue1.ItemsSource = GenerateLimitValues("Min1"); if (this.chartView.Series.Contains(lineSeriesMinValue1)) this.chartView.Series.Remove(lineSeriesMinValue1); this.chartView.Series.Add(lineSeriesMinValue1); } // Adding a target value to chart if (!ItemsSource.IsNull() && ((!GetTargetValue(this).IsNull()) && !GetTargetValue(this).Equals(0.0))) { this.chartView.Series.Add(new LineSeries()); lineSeriesTarget = this.chartView.Series[3] as LineSeries; Style styleTargetLineSeries = new Style(); styleTargetLineSeries.Setters.Add(new Setter(LineSeries.BackgroundProperty, Brushes.Gray)); styleTargetLineSeries.Setters.Add(new Setter(LineSeries.TemplateProperty, null)); lineSeriesTarget.DataPointStyle = styleTargetLineSeries; lineSeriesTarget.DependentValuePath = FieldForDependentValue; lineSeriesTarget.IndependentValuePath = FieldForIndependentValue; lineSeriesTarget.ItemsSource = GenerateLimitValues("Target"); if (this.chartView.Series.Contains(lineSeriesTarget)) this.chartView.Series.Remove(lineSeriesTarget); this.chartView.Series.Add(lineSeriesTarget); } // Adding a max limit to chart if (!ItemsSource.IsNull() && ((!GetMaxLimitValue2(this).IsNull()) && !GetMaxLimitValue2(this).Equals(0.0))) { this.chartView.Series.Add(new LineSeries()); lineSeriesMaxValue2 = this.chartView.Series[4] as LineSeries; Style styleMaxLineSeries = new Style(); styleMaxLineSeries.Setters.Add(new Setter(LineSeries.BackgroundProperty, new SolidColorBrush(Color.FromArgb(255, 255, 0, 0)))); styleMaxLineSeries.Setters.Add(new Setter(LineSeries.TemplateProperty, null)); lineSeriesMaxValue2.DataPointStyle = styleMaxLineSeries; lineSeriesMaxValue2.DependentValuePath = FieldForDependentValue; lineSeriesMaxValue2.IndependentValuePath = FieldForIndependentValue; lineSeriesMaxValue2.ItemsSource = GenerateLimitValues("Max2"); if (this.chartView.Series.Contains(lineSeriesMaxValue2)) this.chartView.Series.Remove(lineSeriesMaxValue2); this.chartView.Series.Add(lineSeriesMaxValue2); } // Adding a min limit to chart if (!ItemsSource.IsNull() && ((!GetMinLimitValue2(this).IsNull()) && !GetMinLimitValue2(this).Equals(0.0))) { this.chartView.Series.Add(new LineSeries()); lineSeriesMinValue2 = this.chartView.Series[5] as LineSeries; Style styleMinLineSeries = new Style(); styleMinLineSeries.Setters.Add(new Setter(LineSeries.BackgroundProperty, new SolidColorBrush(Color.FromArgb(255, 255, 0, 0)))); styleMinLineSeries.Setters.Add(new Setter(LineSeries.TemplateProperty, null)); lineSeriesMinValue2.DataPointStyle = styleMinLineSeries; lineSeriesMinValue2.DependentValuePath = FieldForDependentValue; lineSeriesMinValue2.IndependentValuePath = FieldForIndependentValue; lineSeriesMinValue2.ItemsSource = GenerateLimitValues("Min2"); if (this.chartView.Series.Contains(lineSeriesMinValue2)) this.chartView.Series.Remove(lineSeriesMinValue2); this.chartView.Series.Add(lineSeriesMinValue2); } // Configure axis if (ItemsSource.IsNull() || (((IList)ItemsSource).Count == 0)) { foreach (var actualAxis in this.chartView.ActualAxes) if (actualAxis.Orientation.Equals(AxisOrientation.Y)) { (actualAxis as LinearAxis).Maximum = null; (actualAxis as LinearAxis).Minimum = null; (actualAxis as LinearAxis).ShowGridLines = ShowGridLinesY; (actualAxis as LinearAxis).Visibility = Visibility.Collapsed; } else if (actualAxis.Orientation.Equals(AxisOrientation.X)) { if (actualAxis is DateTimeAxis) { if (!FieldForIndependentValue.IsNullOrEmpty() && FieldForIndependentValue.Contains("DateTime")) { (actualAxis as DateTimeAxis).Maximum = null; (actualAxis as DateTimeAxis).Minimum = null; (actualAxis as DateTimeAxis).Visibility = Visibility.Collapsed; } else (actualAxis as DateTimeAxis).Visibility = Visibility.Collapsed; } else { if (!FieldForIndependentValue.IsNullOrEmpty() && FieldForIndependentValue.Contains("Double")) { (actualAxis as LinearAxis).Maximum = null; (actualAxis as LinearAxis).Minimum = null; (actualAxis as LinearAxis).Visibility = Visibility.Collapsed; (actualAxis as LinearAxis).ShowGridLines = ShowGridLinesX; } else (actualAxis as LinearAxis).Visibility = Visibility.Collapsed; } } } else if ((this.chartView.Axes.Count > 0) && ((!ItemsSource.IsNull()) && ((IList)ItemsSource).Count > 0)) { foreach (var actualAxis in this.chartView.ActualAxes) { if (actualAxis.Orientation.Equals(AxisOrientation.Y)) { (actualAxis as LinearAxis).Maximum = null; (actualAxis as LinearAxis).Minimum = null; (actualAxis as LinearAxis).Maximum = MaximumAxisY; (actualAxis as LinearAxis).Minimum = MinimumAxisY; (actualAxis as LinearAxis).Visibility = Visibility.Visible; (actualAxis as LinearAxis).ShowGridLines = ShowGridLinesY; } else if (actualAxis.Orientation.Equals(AxisOrientation.X)) { if (actualAxis is DateTimeAxis) { if (!FieldForIndependentValue.IsNullOrEmpty() && FieldForIndependentValue.Contains("DateTime")) { (actualAxis as DateTimeAxis).Maximum = null; (actualAxis as DateTimeAxis).Minimum = null; (actualAxis as DateTimeAxis).Maximum = ((IList<ChartItems>)ItemsSource).Select(s => s.ValueXDateTime).LastOrDefault(); (actualAxis as DateTimeAxis).Minimum = ((IList<ChartItems>)ItemsSource).Select(s => s.ValueXDateTime).FirstOrDefault(); (actualAxis as DateTimeAxis).ShowGridLines = ShowGridLinesX; (actualAxis as DateTimeAxis).Visibility = Visibility.Visible; } else (actualAxis as DateTimeAxis).Visibility = Visibility.Collapsed; } else { if (!FieldForIndependentValue.IsNullOrEmpty() && FieldForIndependentValue.Contains("Double")) { (actualAxis as LinearAxis).Maximum = null; (actualAxis as LinearAxis).Minimum = null; if (IntervalAxisX > 0) (actualAxis as LinearAxis).Interval = IntervalAxisX; (actualAxis as LinearAxis).Maximum = ((IList<ChartItems>)ItemsSource).Select(s => s.ValueXDouble).LastOrDefault() + 0.5; (actualAxis as LinearAxis).Minimum = ((IList<ChartItems>)ItemsSource).Select(s => s.ValueXDouble).FirstOrDefault() - 0.5; (actualAxis as LinearAxis).Visibility = Visibility.Visible; (actualAxis as LinearAxis).ShowGridLines = ShowGridLinesX; } else (actualAxis as LinearAxis).Visibility = Visibility.Collapsed; } } } } } }
Any help would be appreciated.
Best regards, Gustavo.