基本上我有一个从DataTable绑定的图表,该源图来自DataGridView。我在图表上有可缩放的函数,我需要使用X Axis SelectionStart和SelectionEnd来计算所选的数据块。
所以我在另一个标签页上的richtextbox中放置了一些最小值和平均值。如下面的代码所示:
//To show the Data from file into the TextBox
richTextBox1.AppendText("\n" + "Heart Average : " + HRM.Active.DataRows.Average(r => r.HeartRate) + "\n");
richTextBox1.AppendText("\n" + "Heart Minimum : " + HRM.Active.DataRows.Min(r => r.HeartRate) + "\n");
richTextBox1.AppendText("\n" + "Heart Maximum : " + HRM.Active.DataRows.Max(r => r.HeartRate) + "\n");
richTextBox1.AppendText("\n" + "Average Speed (KM/H): " + HRM.Active.DataRows.Average(r => r.Speed) + "\n");
richTextBox1.AppendText("\n" + "Maximum Speed : " + HRM.Active.DataRows.Max(r => r.Speed) + "\n");
richTextBox1.AppendText(Environment.NewLine + " - (MPH): " + "");
richTextBox1.AppendText("\n" + "Average Power: " + HRM.Active.DataRows.Average(r => r.Power) + "\n");
richTextBox1.AppendText("\n" + "Maximum Power : " + HRM.Active.DataRows.Max(r => r.Power) + "\n");
richTextBox1.AppendText("\n" + "Average Altitude (KM/H): " + HRM.Active.DataRows.Average(r => r.Altitude) + "\n");
richTextBox1.AppendText("\n" + "Maximum Altitude : " + HRM.Active.DataRows.Max(r => r.Altitude) + "\n");
richTextBox1.AppendText("\n" + "Cadence Average : " + HRM.Active.DataRows.Average(r => r.Cadence) + "\n");
richTextBox1.AppendText("\n" + "Cadence Maximum : " + HRM.Active.DataRows.Max(r => r.Cadence) + "\n");
richTextBox1.AppendText("\n" + "Pressure Average : " + HRM.Active.DataRows.Average(r => r.Pressure) + "\n");
richTextBox1.AppendText("\n" + "Pressure Maximum : " + HRM.Active.DataRows.Max(r => r.Pressure) + "\n");
现在在下面的图片中,您可以看到图表的图像及其显示的数据,以下是将数据表绑定到图表的代码。
protected void drawChart()
{
DataTable dt = new DataTable();
dt.Clear();
foreach (DataGridViewColumn col in dataGridView1.Columns)
{
dt.Columns.Add(col.HeaderText);
}
foreach (DataGridViewRow row in dataGridView1.Rows)
{
DataRow dRow = dt.NewRow();
foreach (DataGridViewCell cell in row.Cells)
{
dRow[cell.ColumnIndex] = cell.Value;
}
dt.Rows.Add(dRow);
}
现在我需要做的是在Graph附近有另一个文本框,每次我缩放并且灰色块出来时它会显示我选择的块的最小值maximiums和averages!然后当我缩小时,它会重置为原始。
如果你不明白我的意思,请给我留言,我会提供更多信息。
答案 0 :(得分:1)
要在缩放或滚动之后根据可见Points
更新统计计算,您需要了解两件事:何时应该你这样做,哪些点是可见的。
要使用的事件是AxisViewChanged
,这很容易。连接完毕后,您可以调用函数来更新统计信息:
private void chart1_AxisViewChanged(object sender, ViewEventArgs e)
{
updateStats();
}
困难的部分是知道Points
集合的哪一部分可见。
乍一看,您可能会认为ViewEventArgs
parm有帮助;毕竟它有如下有希望的数据:NewPosition
和NewSize
。
但仔细观察,你会发现两者都是双打的,所以除非你的XValues
已经从0开始计数,否则他们不会将Points
集合编入索引。
相反,我们必须对这些值进行一些搜索,从左侧为最小值,右侧为最大值。这是一个这样做的功能:
int getVisiblePoint(Chart chart, Series series, bool first)
{
Series S = series;
ChartArea CA = chart.ChartAreas[S.ChartArea];
DataPoint pt = null;
if (first) pt = S.Points.Select(x => x)
.Where(x => x.XValue >= CA.AxisX.ScaleView.ViewMinimum)
.DefaultIfEmpty(S.Points.First()).First();
else pt = S.Points.Select(x => x)
.Where(x => x.XValue <= CA.AxisX.ScaleView.ViewMaximum)
.DefaultIfEmpty(S.Points.Last()).Last();
return S.Points.IndexOf(pt);
}
从这里开始,事情变得容易多了;我们可以对我们的系列做统计,也许是这样:
void updateStats()
{
int firstPt = getVisiblePoint(chart1, chart1.Series[0], true);
int lastPt = getVisiblePoint(chart1, chart1.Series[0], false);
int sCount = chart1.Series.Count;
double[] avg = new double[sCount];
double[] min = new double[sCount];
double[] max = new double[sCount];
for (int i = 0; i < sCount; i++)
{
Series S = chart1.Series[i];
avg[i] = getAverage(S, firstPt, lastPt);
min[i] = getMixMax(S, firstPt, lastPt, true);
max[i] = getMixMax(S, firstPt, lastPt, false);
}
// insert code to display the data here!
}
使用简单的函数进行数学运算:
double getAverage(Series series, int first, int last)
{
double sum = 0;
for (int i = first; i < last; i++) sum += series.Points[i].YValues[0];
return sum / (last - first + 1);
}
double getMixMax(Series series, int first, int last, bool min)
{
double val = 0;
for (int i = first; i < last; i++)
{
double v = series.Points[i].YValues[0];
if ( (min && val > v) || (!min && val >= v)) val = v;
}
return val;
}