Contrôle graphique axe Y échelle automatique de défilement

j'ai cherché sur le net depuis un certain temps maintenant mais je n'ai toujours pas trouvé de bonne solution à mon problème. Je veux faire ms Chart pour automatiquement changer l'axe Y sur le défilement pour s'assurer que tous les points de données sont visibles. Le truc, c'est que j'ai besoin d'avoir la possibilité d'exclure certaines séries de l'utilisation de l'échelle automatique. Jusqu'à présent j'ai seulement trouvé des solutions qui offrent d'itérer à travers toute la collection de points sur AxisViewChanged event, qui ne fonctionne pas bien quand vous avez grand les collections de points et quelques séries à parcourir. Je me demandais s'il y avait un moyen de restreindre la recherche en obtenant des points de données qui se situent entre les valeurs min et max X actuellement visibles. Toute aide serait appréciée.

Modifier Heres l'image. Comme vous pouvez le voir, les chandeliers au milieu ne sont pas entièrement visibles. enter image description here

10
demandé sur L.E.O 2011-03-19 19:13:16

5 réponses

Vous pouvez essayer ce code

        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

6
répondu Stecya 2011-03-19 18:01:23

Utilisez une requête pour trouver quelle série vous voulez utiliser pour trouver ymin et ymax dans le code.

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;
        }
    }
5
répondu Shivaram K R 2011-12-07 04:13:27

il s'agit d'une amélioration mineure par rapport à L'excellente soumission de Shivaram K R, pour empêcher que les valeurs ouvertes, fermées et basses tombent du bas pour les points les plus bas sur les graphiques financiers avec quatre valeurs Y: élevé, faible, ouvert fermé.

// 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; 
    } 
} 
3
répondu Chris J 2012-01-21 15:22:25

basé sur les réponses précédentes

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

il se peut que vous ayez d'autres séries dans la chartarea. Dans ce cas, vous choisissez le haut et le bas de toutes les séries dans la région au lieu d'un seul.

cordialement,

Matthijs

0
répondu user369122 2012-09-19 09:31:42

les réponses ci-dessus m'ont été très utiles. Cependant, j'ai une carte avec plusieurs zones de cartographie. J'ai adapté le code à toutes les zones des cartes:

    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;
      }
    }
0
répondu Boris Zinchenko 2015-02-09 08:55:44