title: Adding a TextBlock (or label) on the end of a LineSeries DataPoint of a DataVisualizationChart
body: <p>I'm creating a User Control componente of type DataVisualization.Chart. Right now, he accepts 4 range limits (1 range minimum of accept value and 1 maximum, also 1 range minimum of warning value and 1 maximum warning range value). 
  So far, so good. It works. But i need to add a TextBlock (or label, or TextBox, whatever) at the end of the LineSeries.</p>
  
  <p>This is my actual LineSeries:</p>
  
  <p><img src="https://i.stack.imgur.com/07XQb.png" alt="Chart without label"></p>
  
  <p>Now i need to make something like this:</p>
  
  <p><img src="https://i.stack.imgur.com/dDjQv.png" alt="Chart with label"></p>
  
  <p>Even if the result is not the same, i need to put a label or textblock at the end of every LineDataPoint. </p>
  
  <p><strong>Edit 1:</strong></p>
  
  <p>This is how my list of items is generated:</p>
  
  <pre><code>  /// &lt;summary&gt;
    /// Generate ItemsSource to use with chart component
    /// &lt;/summary&gt;
    /// &lt;returns&gt;A observable collection items of ChartItems type&lt;/returns&gt;
    public ObservableCollection&lt;ChartItems&gt; GenerateActualValues()
    {
        var itemsSource = ItemsSource as IEnumerable;
         if (itemsSource.IsNull())
            return null;
  
         // Get all values from ItemsSource to set Axis Y of Chart
  
         List&lt;Double&gt; listAxisY = new List&lt;Double&gt;();
  
         ObservableCollection&lt;ChartItems&gt; chartItems = new ObservableCollection&lt;ChartItems&gt;();
  
          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 &gt; 0)
              {
                  if (GetMaxLimitValue1(this) &gt; listAxisY.Max())
                      maxValue = GetMaxLimitValue1(this);
                  else
                      maxValue = listAxisY.Max();
  
                  if (GetMinLimitValue1(this) &lt; 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;
      }
  </code></pre>
  
  <p>Basically, it generate a new ItemsSource to use in my Chart. Now, to generate those extra lines:</p>
  
  <pre><code>/// &lt;summary&gt;
  /// Generate a ItemsSource using param option informed
  /// &lt;/summary&gt;
  /// &lt;param name="option"&gt;Min1, Max1, Min2, Max2 or Target Value&lt;/param&gt;
  /// &lt;returns&gt;Observable Collection of ChartItems&lt;/returns&gt;
  public ObservableCollection&lt;ChartItems&gt; GenerateLimitValues(String option)
  {
      var itemsSource = ItemsSource as IEnumerable;
  
      if (itemsSource.IsNull())
          return null;
  
      Double? valueY = 0.0;
  
      ObservableCollection&lt;ChartItems&gt; chartItems = new ObservableCollection&lt;ChartItems&gt;();
  
      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;
  }
  </code></pre>
  
  <p>Now, this is where all the things work in my Chart:</p>
  
  <pre><code>/// &lt;summary&gt;
  /// Generates series with values for chart
  /// &lt;/summary&gt;
  public void RenderizeChart()
  {
      while (this.chartView.Series.Count() - 1 &gt;= 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's 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&lt;Setter&gt; setterList = new List&lt;Setter&gt;();
  
                      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() &amp;&amp; ((!GetMaxLimitValue1(this).IsNull()) &amp;&amp; !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() &amp;&amp; ((!GetMinLimitValue1(this).IsNull()) &amp;&amp; !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() &amp;&amp; ((!GetTargetValue(this).IsNull()) &amp;&amp; !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() &amp;&amp; ((!GetMaxLimitValue2(this).IsNull()) &amp;&amp; !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() &amp;&amp; ((!GetMinLimitValue2(this).IsNull()) &amp;&amp; !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() &amp;&amp; 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() &amp;&amp; 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 &gt; 0) &amp;&amp; ((!ItemsSource.IsNull()) &amp;&amp; ((IList)ItemsSource).Count &gt; 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() &amp;&amp; FieldForIndependentValue.Contains("DateTime"))
                          {
                              (actualAxis as DateTimeAxis).Maximum = null;
                              (actualAxis as DateTimeAxis).Minimum = null;
  
                              (actualAxis as DateTimeAxis).Maximum = ((IList&lt;ChartItems&gt;)ItemsSource).Select(s =&gt; s.ValueXDateTime).LastOrDefault();
                              (actualAxis as DateTimeAxis).Minimum = ((IList&lt;ChartItems&gt;)ItemsSource).Select(s =&gt; 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() &amp;&amp; FieldForIndependentValue.Contains("Double"))
                          {
                              (actualAxis as LinearAxis).Maximum = null;
                              (actualAxis as LinearAxis).Minimum = null;
  
                              if (IntervalAxisX &gt; 0)
                                  (actualAxis as LinearAxis).Interval = IntervalAxisX;
  
                              (actualAxis as LinearAxis).Maximum = ((IList&lt;ChartItems&gt;)ItemsSource).Select(s =&gt; s.ValueXDouble).LastOrDefault() + 0.5;
                              (actualAxis as LinearAxis).Minimum = ((IList&lt;ChartItems&gt;)ItemsSource).Select(s =&gt; s.ValueXDouble).FirstOrDefault() - 0.5;
  
                              (actualAxis as LinearAxis).Visibility = Visibility.Visible;
  
                              (actualAxis as LinearAxis).ShowGridLines = ShowGridLinesX;
  
  
                          }
                          else
                          (actualAxis as LinearAxis).Visibility = Visibility.Collapsed;
                      }
                  }
              }
          }
      }
  }
  </code></pre>
  
  <p>Any help will be appreciated.</p>
  
  <p>Best Regards,
  Gustavo.</p>