C# 图表控件Y轴滚动时自动缩放

C# 图表控件Y轴滚动时自动缩放,c#,scale,mschart,C#,Scale,Mschart,我已经上网搜索了一段时间了,但仍然没有找到解决我问题的好办法。我想让MS图表在滚动时自动重新缩放Y轴,以确保所有数据点都可见。这里的转折点是,我需要有能力排除某些系列被用于自动缩放。到目前为止,我只找到了提供在AxisViewChanged事件上迭代整个点集合的解决方案,当您有大量点集合和几个系列要迭代时,这种方法不起作用。我想知道是否有办法通过获取当前可见的最小值和最大值之间的数据点来缩小搜索范围。任何帮助都将不胜感激 编辑这是图像。正如你所看到的,在中间的烛台并不完全可见。 您可以尝试此代码

我已经上网搜索了一段时间了,但仍然没有找到解决我问题的好办法。我想让MS图表在滚动时自动重新缩放Y轴,以确保所有数据点都可见。这里的转折点是,我需要有能力排除某些系列被用于自动缩放。到目前为止,我只找到了提供在AxisViewChanged事件上迭代整个点集合的解决方案,当您有大量点集合和几个系列要迭代时,这种方法不起作用。我想知道是否有办法通过获取当前可见的最小值和最大值之间的数据点来缩小搜索范围。任何帮助都将不胜感激

编辑这是图像。正如你所看到的,在中间的烛台并不完全可见。 您可以尝试此代码

        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;
DateTime date=DateTime.Now;
chart1.ChartAreas[0]。AxisX.Minimum=0;
chart1.ChartAreas[0].AxisX.Maximum=20;
随机r=新随机((int)date.Ticks);
chart1.系列[0]。ChartType=系列ChartType.烛台;
图表1.系列[0]。颜色=颜色。绿色;
chart1.Series[0].XValueType=ChartValueType.Time;
chart1.系列[0]。IsXValueIndexed=true;
图表1.系列[0]。YValuesPerPoint=4;
chart1.Series[0].CustomProperties=“MaxPixelPointWidth=10”;
对于(int i=0;i<100;i++)
{
DataPoint point=newdatapoint(date.AddHours(i).ToOADate(),newdouble[]{r.Next(10,20),r.Next(30,40),r.Next(20,30),r.Next(20,30)});
图表1.系列[0]。点。添加(点);
}
int min=(int)chart1.ChartAreas[0].AxisX.Minimum;
int max=(int)chart1.ChartAreas[0].axix.max;
如果(最大值>图表1.Series[0].点数)
max=chart1.Series[0]。Points.Count;
var points=chart1.Series[0]。points.Skip(min)。Take(max-min);
var minValue=points.Min(x=>x.yValue[0]);
var maxValue=points.Max(x=>x.yvalue[1]);
chart1.ChartAreas[0]。AxisY.Minimum=minValue;
chart1.ChartAreas[0]。AxisY.max=maxValue;

使用查询找出要在代码中查找ymin和ymax的序列

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;
        }
    }
private void chart1\u AxisViewChanged(对象发送方,ViewEventArgs e)
{
if(e.Axis.AxisName==AxisName.X)
{
int start=(int)e.Axis.ScaleView.viewmimum;
int end=(int)e.Axis.ScaleView.viewmimum;
//Series ss=chart1.Series.FindByName(“SeriesName”);
//使用ss代替chart1.Series[0]
double[]temp=chart1.Series[0]。Points.Where((x,i)=>i>=start&&i x.y值[0])。ToArray();
双ymin=最低温度();
双ymax=最高温度();
chart1.ChartAreas[0].AxisY.ScaleView.Position=ymin;
chart1.ChartAreas[0].AxisY.ScaleView.Size=ymax-ymin;
}
}

这是对Shivaram K R提交的优秀报告的一个小小改进,以防止在具有四个Y值(高、低、开-关)的金融图表上,开盘、收盘和低点从底部跌落

// 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; 
    } 
} 
//表单构造函数中有以下行
this.chart1.AxisViewChanged+=新事件处理程序(this.chart1\u AxisViewChanged);
私有无效图表1\u AxisViewChanged(对象发送方,ViewEventArgs e)
{ 
if(e.Axis.AxisName==AxisName.X)
{ 
int start=(int)e.Axis.ScaleView.viewmimum;
int end=(int)e.Axis.ScaleView.viewmimum;
//使用两个单独的阵列,一个用于高(与Shavram最初的temp相同)
//和一个用于设置Y轴最小值的新低点。
double[]temphhighs=chart1.Series[0]。Points.Where((x,i)=>i>=start&i x.y值[0])。ToArray();
double[]tempLows=chart1.Series[0]。Points.Where((x,i)=>i>=start&i x.y值[1])。ToArray();
双ymin=tempLows.Min();
双ymax=tempHighs.Max();
chart1.ChartAreas[0].AxisY.ScaleView.Position=ymin;
chart1.ChartAreas[0].AxisY.ScaleView.Size=ymax-ymin;
} 
} 

基于前面的答案

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;
        }
    }
private void chart1\u AxisViewChanged(对象发送方,ViewEventArgs e)
{
if(e.Axis.AxisName==AxisName.X)
{
int start=(int)e.Axis.ScaleView.viewmimum;
int end=(int)e.Axis.ScaleView.viewmimum;
List allNumbers=新列表();
foreach(图表1.系列中的系列项目)
allNumbers.AddRange(item.Points.Where((x,i)=>i>=start&i 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;
}
}
这可能是你在图表区有更多的系列。在本例中,您选择区域中所有系列的高和低,而不是仅选择一个系列

问候,


Matthijs

以上的答案对我很有帮助。但是,我有一个带有多个图表区域的图表。我已经调整了代码,以扩大到所有图表区域:

    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;
      }
    }
foreach(图表1中的图表区域。图表区域)
{
List allNumbers=新列表();
foreach(图表1.系列中的系列项目)
if(item.ChartArea==area.Name)
allNumbers.AddRange(item.Points.Where((x,i)=>i>=start&i x.YValues[0]).ToList();
double ymin=allNumbers.Min();
double ymax=allNumbers.Max();
如果(ymax>ymin)
{
双偏移=0.02*(ymax-ymin);
area.AxisY.max=ymax+偏移量;
area.AxisY.Minimum=ymin-偏移量;
}
}

Mmh我不清楚。。。您想在滚动X轴时重新缩放Y轴,对吗?否则对我来说就没有意义了。顺便说一句,你能给出一个你需要的视觉例子吗@