Как получить масштаб вторичной оси на основе значений моей серии? - PullRequest
1 голос
/ 23 апреля 2019

Я использую System.Web.UI.DataVisualization. Диаграммы для создания диаграмм в MVC.

У меня есть диаграмма, отображающая значения в StackedColumn100 SeriesChartType с соответствующими значениями оси Y на основной оси Y на левой стороне.

Поскольку это серия столбцов, уложенных на 100%, первичная ось Y масштабируется от 0 до 100.

Затем я добавил вторичную серию в виде линии SeriesChartType, привязанной к вторичной оси (с правой стороны). Я хотел бы, чтобы эта ось корректировала свой масштаб на основе значений в серии, но это не так. Независимо от того, что является самым высоким значением этой серии, вторичная ось Y также имеет шкалу от 0 до 100.

Если я вручную установлю максимальное значение для вторичной оси Y следующим образом: chart.ChartAreas[0].AxisY2.Maximum = 20;. Это работает, но я не хочу этого делать, поскольку максимальное значение может сильно различаться в зависимости от используемых критериев поиска.

Я действительно пытался найти решение для этого, но не могу. Согласно документации и образцам, кажется, что масштаб должен быть основан на значениях серии, но я не понимаю, как это работает. Любая помощь будет принята с благодарностью!

Ниже приведена отдельная функция тестирования, воссоздающая проблему. Я вызываю функцию из моего представления со следующей строкой:

<p><img src="@Url.Action("CreateChart_TestSecondaryAxis")" /> </p>

public FileResult CreateChart_TestSecondaryAxis()
        {
            System.Web.UI.DataVisualization.Charting.Chart chart = new System.Web.UI.DataVisualization.Charting.Chart();
            chart.Width = 800;
            chart.Height = 400;
            chart.BackColor = Color.FromArgb(211, 223, 240);
            chart.BorderlineDashStyle = ChartDashStyle.Solid;
            chart.BackSecondaryColor = Color.White;
            chart.BackGradientStyle = GradientStyle.TopBottom;
            chart.BorderlineWidth = 1;
            chart.Palette = ChartColorPalette.BrightPastel;
            chart.BorderlineColor = Color.FromArgb(26, 59, 105);
            chart.RenderType = RenderType.BinaryStreaming;
            chart.BorderSkin.SkinStyle = BorderSkinStyle.Emboss;
            chart.AntiAliasing = AntiAliasingStyles.All;
            chart.TextAntiAliasingQuality = TextAntiAliasingQuality.Normal;

            ChartArea chartArea = new ChartArea();
            chartArea.Name = "TestSecondaryAxis";
            chartArea.BackColor = Color.Transparent;
            chartArea.AxisX.IsLabelAutoFit = false;
            chartArea.AxisY.IsLabelAutoFit = false;
            chartArea.AxisX.LabelStyle.Font =
               new Font("Verdana,Arial,Helvetica,sans-serif",
                        8F, FontStyle.Regular);
            chartArea.AxisY.LabelStyle.Font =
               new Font("Verdana,Arial,Helvetica,sans-serif",
                        8F, FontStyle.Regular);
            chartArea.AxisY.LineColor = Color.FromArgb(64, 64, 64, 64);
            chartArea.AxisX.LineColor = Color.FromArgb(64, 64, 64, 64);
            chartArea.AxisY.MajorGrid.LineColor = Color.FromArgb(64, 64, 64, 64);
            chartArea.AxisX.MajorGrid.LineColor = Color.FromArgb(64, 64, 64, 64);

            chartArea.AxisX.Title = "Airport";
            chartArea.AxisY.Title = "LandingConf";
            chartArea.AxisY.TextOrientation = TextOrientation.Rotated270;
            chartArea.AxisX.LabelStyle.IsEndLabelVisible = true;
            chart.ChartAreas.Add(chartArea);

            Series seriesPrimaryAxisConf3 = new Series();
            seriesPrimaryAxisConf3.Name = "Conf 3";
            seriesPrimaryAxisConf3.IsValueShownAsLabel = false;
            seriesPrimaryAxisConf3.Color = Color.Blue;
            seriesPrimaryAxisConf3.ChartType = SeriesChartType.StackedColumn100;
            seriesPrimaryAxisConf3.BorderWidth = 2;
            seriesPrimaryAxisConf3.ChartArea = "TestSecondaryAxis";
            DataPoint point;


            for (int i = 1; i < 11; i++)
            {
                point = new DataPoint();
                point.AxisLabel = "Airport" + i.ToString();
                point.YValues = new double[] { i };

                seriesPrimaryAxisConf3.Points.Add(point);
            }

            chart.Series.Add(seriesPrimaryAxisConf3);

            Series seriesPrimaryAxisConfFull = new Series();
            seriesPrimaryAxisConfFull.Name = "Conf Full";
            seriesPrimaryAxisConfFull.IsValueShownAsLabel = false;
            seriesPrimaryAxisConfFull.Color = Color.Red;
            seriesPrimaryAxisConfFull.ChartType = SeriesChartType.StackedColumn100;
            seriesPrimaryAxisConfFull.BorderWidth = 2;
            seriesPrimaryAxisConfFull.ChartArea = "TestSecondaryAxis";


            for (int i = 1; i < 11; i++)
            {
                point = new DataPoint();
                point.AxisLabel = "Airport" + i.ToString();
                point.YValues = new double[] { 11-i };

                seriesPrimaryAxisConfFull.Points.Add(point);
            }

            chart.Series.Add(seriesPrimaryAxisConfFull);

            Series seriesSecondaryAxisNoOfFlights = new Series();
            seriesSecondaryAxisNoOfFlights.Name = "NoOfFLights";
            seriesSecondaryAxisNoOfFlights.IsValueShownAsLabel = false;
            seriesSecondaryAxisNoOfFlights.Color = Color.Red;
            seriesSecondaryAxisNoOfFlights.ChartType = SeriesChartType.Line;
            seriesSecondaryAxisNoOfFlights.BorderWidth = 2;
            seriesSecondaryAxisNoOfFlights.ChartArea = "TestSecondaryAxis";


            for (int i = 1; i < 11; i++)
            {
                point = new DataPoint();
                point.AxisLabel = "Airport" + i.ToString();
                point.YValues = new double[] { i };

                seriesSecondaryAxisNoOfFlights.Points.Add(point);
            }

            chart.Series.Add(seriesSecondaryAxisNoOfFlights);
            chart.Series["NoOfFLights"].YAxisType = AxisType.Secondary;
            chart.ChartAreas["TestSecondaryAxis"].AxisY2.LineColor = Color.Transparent;
            chart.ChartAreas["TestSecondaryAxis"].AxisY2.MajorGrid.Enabled = false;
            chart.ChartAreas["TestSecondaryAxis"].AxisY2.MajorTickMark.Enabled = false;

            MemoryStream ms = new MemoryStream();
            chart.SaveImage(ms);
            return File(ms.GetBuffer(), @"image/png");
        }

1 Ответ

0 голосов
/ 23 мая 2019

MSChart - хороший элемент управления, но, к сожалению Microsoft всегда не могла правильно документ это.

И с последними изменениями в MSDN дела пошли на от плохого к худшему , поэтому я не могу на самом деле указать на правила, действующие для различных ChartTypes.

В вашем случае я вычитаю это (довольно дурацкое) правило:

Чтобы прикрепить не 100% -серию к независимо масштабируемой вторичной оси Y это должна быть первая серия, но все еще нужно добавить серию первый.

Итак, если вы хотите получить такой результат:

enter image description here

.. вам нужно адаптировать код. Вот необходимые изменения и дополнения ..:

Сначала нам нужно вставить ряд строк на фронте , но сделать это после для серии stack100 добавлена ​​метка ..:

chart.Series.Insert(0, seriesSecondaryAxisNoOfFlights);  // instead of adding it

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

Код события PostPaint, например:

private void Chart_PostPaint(object sender, ChartPaintEventArgs e)
{
    Chart chart = sender as Chart;  //*
    Series s = chart.Series[0];  // make sure to pick the right one!

    Axis ax = chart.ChartAreas[0].AxisX;
    Axis ay = chart.ChartAreas[0].AxisY2;  // !!

    var pts = s.Points.Select(x => 
        new PointF((float)ax.ValueToPixelPosition(x.XValue),
                   (float)ay.ValueToPixelPosition(x.YValues[0])));

    using (Pen pen = new Pen(s.Color, s.BorderWidth))
            e.ChartGraphics.Graphics.DrawLines(pen, pts.ToArray());
}

Для этой работы серии необходимо допустимых х-значений. Поэтому добавьте эту строку:

point.XValue = i;  // set both x and y-values!

Я также добавил несколько толчков к позиционированию оси:

ChartArea ca = chart.ChartAreas["TestSecondaryAxis"];
ca.AxisY.Maximum = 100;
ca.AxisX.Minimum = 0.5;
ca.AxisX.IntervalOffset = 0.5;
...