Автоматическое масштабирование оси Y при прокрутке
Я уже некоторое время искал сеть, но до сих пор не нашел хорошего решения моей проблемы. Я хочу, чтобы MS Chart автоматически масштабировала ось Y при прокрутке, чтобы убедиться, что все точки данных видны. Твист здесь заключается в том, что мне нужно иметь возможность исключать некоторые серии из автоматического масштабирования. До сих пор я нашел решения, предлагающие итерацию по всей коллекции точек в событии AxisViewChanged, что плохо работает, когда у вас есть большие коллекции очков и несколько серий для повторения. Мне было интересно, есть ли способ сузить поиск, получив точки данных, которые находятся между видимыми в настоящий момент значениями min и max X. Любая помощь будет оценена.
Изменить. Символ изображения. Как вы можете видеть, подсвечники посередине не совсем видны.
![enter image description here]()
Ответы
Ответ 1
вы можете попробовать этот код
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]()
Ответ 2
Используйте запрос, чтобы узнать, какую серию вы хотите использовать для поиска 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;
}
}
Ответ 3
Это небольшое улучшение в отличном представлении от 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 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;
}
}
Ответ 4
Основываясь на предыдущих ответах
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;
}
}
Возможно, у вас больше сериалов в chartarea. В этом случае вы выбираете максимум и минимум всех серий в области, а не только один.
С уважением,
Маттийс
Ответ 5
Выше ответы были очень полезны для меня. Тем не менее, у меня есть диаграмма с несколькими диаграммами. Я адаптировал код для масштабирования до всех областей диаграммы:
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;
}
}