Добавление TextBlock (или метки) в конец DataPoint LineSeries объекта DataVisualizationChart

1

Я создаю компонент User Control типа DataVisualization.Chart. В настоящее время он принимает 4 диапазона (1 минимальное значение принимаемого значения и 1 максимум, а также 1 минимальное значение диапазона предупреждения и 1 максимальное значение диапазона предупреждения). Все идет нормально. Оно работает. Но мне нужно добавить TextBlock (или ярлык, или TextBox, что угодно) в конце LineSeries.

Это мой фактический LineSeries:

Изображение 174551

Теперь мне нужно сделать что-то вроде этого:

Изображение 174551

Даже если результат не тот же, мне нужно поместить ярлык или текстовый блок в конец каждого LineDataPoint.

Изменить 1:

Вот как генерируется мой список элементов:

  /// <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;
    }

В принципе, он генерирует новый ItemSource для использования в моем графике. Теперь, чтобы сгенерировать эти дополнительные строки:

/// <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;
}

Теперь, когда все вещи работают в моей диаграмме:

/// <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;
                    }
                }
            }
        }
    }
}

Любая помощь будет оценена.

С наилучшими пожеланиями, Густаво.

  • 0
    Как вы добавили эти строки? Я реализовал их для Silverlight, используя внутренний холст диаграммы ( vortexwolf.wordpress.com/2011/09/15/… ). Легко добавить текстовый блок в Canvas, если вы реализовали строки так же, как в моей статье.
  • 0
    Hy vorrtex, я добавил немного кода. Извините за задержку, я путешествую в эти дни.
Показать ещё 3 комментария
Теги:
wpf
charts
data-visualization
wpftoolkit

1 ответ

1

Как оказалось, нетрудно добавить пользовательские элементы в диаграмму. Вы должны получить область диаграммы, вычислить позиции своих элементов и просто добавить их при добавлении в любую панель.

Вот полный пример:

private Canvas canvas;

public MainWindow()
{
    InitializeComponent();

    chart.Loaded += this.OnChartLoaded;
}

private void OnChartLoaded(object sender, RoutedEventArgs e)
{
    var chartArea = (Panel)chart.GetType().GetProperty("ChartArea", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(chart, null);

    // create a canvas to which all text blocks will be added
    this.canvas = new Canvas();
    chartArea.Children.Add(this.canvas);
}

public void AddAllLineLabels() 
{
    // add a red label
    double value = 15;
    var text = new TextBlock() { Text = value.ToString(), Foreground = Brushes.Red };
    AddTextToCanvas(canvas, text, value);

    // add a green label
    value = 19;
    text = new TextBlock() { Text = value.ToString(), Foreground = Brushes.Green };
    AddTextToCanvas(canvas, text, value);
}

private void AddTextToCanvas(Canvas canvas, TextBlock text, double value)
{
    var valuesAxis = chart.ActualAxes.OfType<LinearAxis>().FirstOrDefault(ax => ax.Orientation == AxisOrientation.Y);

    var min = valuesAxis.ActualMinimum.Value;
    var max = valuesAxis.ActualMaximum.Value;

    var maxPixels = valuesAxis.ActualHeight;
    var valuePixels = (value - min) / (max - min) * maxPixels; // from the bottom edge to the value in pixels

    Canvas.SetRight(text, 5); // 5 is a padding from the right edge, you can use any number
    Canvas.SetBottom(text, valuePixels);
    canvas.Children.Add(text);
}

Если вы вызываете метод AddAllLineLabels, он отображает красное число 15 и зеленый номер 19.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню