I've been searching the net for some time now yet still haven't found any good solution to my problem. I want to make MS Chart to automatically rescale Y axis on scrolling to make sure that all data points are visible. The twist here is that I need to have the ability to exclude certain series from being used for auto scale. So far I only found solutions that offer to iterate through the entire point collection on AxisViewChanged event, which doesn't work well when you have large collections of points and a few series to iterate through. I was wondering if there was any way to narrow the search by obtaining data points that are between currently visible min and max X values. Any help would be appreciated.
Edit Heres the image. As you can see the candlesticks in the middle aren't entirely visible.
you can try this 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;
Use a query to find out which series you want to use for finding ymin and ymax in the 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;
}
}
This is a minor improvement on the excellent submission from Shivaram K R, to prevent open, close and low dropping off the bottom for the lowest points on financial charts with four Y values: high, low, open close.
// 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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With