11 Stimmen

Chart Control Y-Achse automatisch skalieren beim Scrollen

Ich suche schon seit einiger Zeit im Netz, habe aber noch keine gute Lösung für mein Problem gefunden. Ich möchte MS Chart dazu bringen, die Y-Achse beim Scrollen automatisch neu zu skalieren, um sicherzustellen, dass alle Datenpunkte sichtbar sind. Der Clou dabei ist, dass ich die Möglichkeit haben muss, bestimmte Serien von der automatischen Skalierung auszuschließen. Bisher habe ich nur Lösungen gefunden, die die gesamte Punktesammlung beim AxisViewChanged-Ereignis durchlaufen, was nicht gut funktioniert, wenn man große Punktesammlungen und nur wenige Serien hat, die durchlaufen werden müssen. Ich habe mich gefragt, ob es eine Möglichkeit gibt, die Suche einzugrenzen, indem Datenpunkte abgerufen werden, die zwischen den derzeit sichtbaren minimalen und maximalen X-Werten liegen. Für jede Hilfe wäre ich dankbar.

bearbeiten Hier ist das Bild. Wie Sie sehen können, sind die Kerzenständer in der Mitte nicht ganz sichtbar. enter image description here

6voto

Stecya Punkte 22308

Können Sie diesen Code ausprobieren

        DateTime date = DateTime.Now;
        chart1.ChartAreas[0].AxisX.Minimum = 0;
        chart1.ChartAreas[0].AxisX.Maximum = 20;
        Random r = new Random((int)date.Ticks);

        chart1.Series[0].ChartType = SeriesChartType.Candlestick;
        chart1.Series[0].Color = Color.Green;
        chart1.Series[0].XValueType = ChartValueType.Time;
        chart1.Series[0].IsXValueIndexed = true;
        chart1.Series[0].YValuesPerPoint = 4;
        chart1.Series[0].CustomProperties = "MaxPixelPointWidth=10";
        for (int i = 0; i < 100; i++ )
        {
            DataPoint point = new DataPoint(date.AddHours(i).ToOADate(), new double[] { r.Next(10, 20), r.Next(30, 40), r.Next(20, 30), r.Next(20, 30) });
            chart1.Series[0].Points.Add(point);
        }

        int min = (int)chart1.ChartAreas[0].AxisX.Minimum;
        int max = (int)chart1.ChartAreas[0].AxisX.Maximum;

        if (max > chart1.Series[0].Points.Count)
            max = chart1.Series[0].Points.Count;

        var points = chart1.Series[0].Points.Skip(min).Take(max - min);

        var minValue = points.Min(x => x.YValues[0]);
        var maxValue = points.Max(x => x.YValues[1]);

        chart1.ChartAreas[0].AxisY.Minimum = minValue;
        chart1.ChartAreas[0].AxisY.Maximum = maxValue;

enter image description here

6voto

Shivaram K R Punkte 91

Verwenden Sie eine Abfrage, um herauszufinden, welche Reihen Sie für die Ermittlung von ymin und ymax im Code verwenden möchten.

private void chart1_AxisViewChanged(object sender, ViewEventArgs e)
    {
        if (e.Axis.AxisName == AxisName.X)
        {
            int start = (int)e.Axis.ScaleView.ViewMinimum;
            int end = (int)e.Axis.ScaleView.ViewMaximum;

            // Series ss = chart1.Series.FindByName("SeriesName");
            // use ss instead of chart1.Series[0]

            double[] temp = chart1.Series[0].Points.Where((x, i) => i >= start && i <= end).Select(x => x.YValues[0]).ToArray();
            double ymin = temp.Min();
            double ymax = temp.Max();

            chart1.ChartAreas[0].AxisY.ScaleView.Position = ymin;
            chart1.ChartAreas[0].AxisY.ScaleView.Size = ymax - ymin;
        }
    }

3voto

Chris J Punkte 31

Dies ist eine geringfügige Verbesserung der hervorragenden Vorlage von Shivaram K. R., um zu verhindern, dass Open, Close und Low für die niedrigsten Punkte in Finanzdiagrammen mit vier Y-Werten (High, Low, Open Close) nach unten fallen.

// The following line goes in your form constructor
this.chart1.AxisViewChanged += new EventHandler<ViewEventArgs> (this.chart1_AxisViewChanged);

private void chart1_AxisViewChanged(object sender, ViewEventArgs e)
{ 
    if (e.Axis.AxisName == AxisName.X) 
    { 
        int start = (int)e.Axis.ScaleView.ViewMinimum; 
        int end = (int)e.Axis.ScaleView.ViewMaximum; 
        // Use two separate arrays, one for highs (same as temp was in Shavram's original)
        // and a new one for lows which is used to set the Y axis min.
        double[] tempHighs = chart1.Series[0].Points.Where((x, i) => i >= start && i <= end).Select(x => x.YValues[0]).ToArray();
        double[] tempLows = chart1.Series[0].Points.Where((x, i) => i >= start && i <= end).Select(x => x.YValues[1]).ToArray();
        double ymin = tempLows.Min();
        double ymax = tempHighs.Max();

        chart1.ChartAreas[0].AxisY.ScaleView.Position = ymin; 
        chart1.ChartAreas[0].AxisY.ScaleView.Size = ymax - ymin; 
    } 
}

0voto

user369122 Punkte 742

Basierend auf früheren Antworten

private void chart1_AxisViewChanged(object sender, ViewEventArgs e)
    {
        if(e.Axis.AxisName == AxisName.X)
        {
            int start = (int)e.Axis.ScaleView.ViewMinimum;
            int end = (int)e.Axis.ScaleView.ViewMaximum;

            List<double> allNumbers = new List<double>();

            foreach(Series item in chart1.Series)
                allNumbers.AddRange(item.Points.Where((x, i) => i >= start && i <= end).Select(x => x.YValues[0]).ToList());

            double ymin = allNumbers.Min();
            double ymax = allNumbers.Max();

            chart1.ChartAreas[0].AxisY.ScaleView.Position = ymin;
            chart1.ChartAreas[0].AxisY.ScaleView.Size = ymax - ymin;
        }
    }

Es könnte sein, dass Sie mehrere Reihen im Diagrammbereich haben. In diesem Fall wählen Sie den Höchst- und Tiefstwert aller Serien in dem Bereich aus, anstatt nur eine.

Grüße,

Matthijs

0voto

Boris Zinchenko Punkte 1836

Die obigen Antworten waren sehr hilfreich für mich. Ich habe jedoch ein Diagramm mit mehreren Diagrammbereichen. Ich habe den Code so angepasst, dass er sich auf alle Diagrammbereiche erstreckt:

    foreach (ChartArea area in chart1.ChartAreas)
    {
      List<double> allNumbers = new List<double>();

      foreach (Series item in chart1.Series)
        if (item.ChartArea == area.Name)
          allNumbers.AddRange(item.Points.Where((x, i) => i >= start && i <= end).Select(x => x.YValues[0]).ToList());

      double ymin = allNumbers.Min();
      double ymax = allNumbers.Max();

      if (ymax > ymin)
      {
        double offset = 0.02 * (ymax - ymin);
        area.AxisY.Maximum = ymax + offset;
        area.AxisY.Minimum = ymin - offset;
      }
    }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X