Microsoft Chart Control - перерисовать диаграмму после сбоя (красный крест)
У меня есть treeView
element
где каждый узел представляет двойной список.
Я использую DataVisualization.Charting
управление для отображения значений в list
,
Для некоторых списков я получаю исключение после RecalculateAxesScale
(System.OverflowException: Value was either too large or too small for a Decimal).
Я игнорирую эту ошибку, и поэтому на графике отображается большой красный крест.
Теперь, когда я нажимаю на другой узел, я хочу отобразить диаграмму этого двойного списка (которая действительна), но моя диаграмма не перерисовывается. Он всегда отображает красный X.
Мой код:
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
//Refresh chart:
chart1.Series.Clear();
chart1.ResetAutoValues();
chart1.ResetText();
//plot new doublelist
var series = new Series
{
Name = "name",
Color = color,
ChartType = SeriesChartType.Line,
ChartArea = "chartName"
};
this.chart1.Series.Add(series);
series.Points.DataBindY(doubleList);
var chartArea = chart1.ChartAreas["chartName"];
chartArea.RecalculateAxesScale();
chartArea.AxisX.Minimum = 1;
chartArea.AxisX.Maximum = doubleList.Count;
chartArea.CursorX.AutoScroll = true;
chartArea.CursorY.AutoScroll = true;
// Allow user to select area for zooming
chartArea.CursorX.IsUserEnabled = true;
chartArea.CursorX.IsUserSelectionEnabled = true;
// Set automatic zooming`<br>
chartArea.AxisX.ScaleView.Zoomable = true;
chartArea.AxisY.ScaleView.Zoomable = true;
chartArea.AxisX.ScrollBar.IsPositionedInside = true;
//reset zoom
chartArea.AxisX.ScaleView.ZoomReset();
chart1.Invalidate();
}
[РЕДАКТИРОВАТЬ]
Тип dblList:
List<double> doubleList= (from s in myData select s.value).ToList();
Полный стек исключений:
{System.OverflowException: Value was either too large or too small for a Decimal.
at System.Decimal.FCallMultiply(Decimal& d1, Decimal& d2)
at System.Decimal.op_Multiply(Decimal d1, Decimal d2)
at System.Windows.Forms.DataVisualization.Charting.Axis.RoundedValues(Double inter, Boolean shouldStartFromZero, Boolean autoMax, Boolean autoMin, Double& min, Double& max)
at System.Windows.Forms.DataVisualization.Charting.Axis.EstimateNumberAxis(Double& minimumValue, Double& maximumValue, Boolean shouldStartFromZero, Int32 preferredNumberOfIntervals, Boolean autoMaximum, Boolean autoMinimum)
at System.Windows.Forms.DataVisualization.Charting.Axis.EstimateAxis(Double& minimumValue, Double& maximumValue, Boolean autoMaximum, Boolean autoMinimum)
at System.Windows.Forms.DataVisualization.Charting.Axis.EstimateAxis()
at System.Windows.Forms.DataVisualization.Charting.ChartArea.SetDefaultAxesValues()
at System.Windows.Forms.DataVisualization.Charting.ChartArea.SetData(Boolean initializeAxes, Boolean checkIndexedAligned)
at System.Windows.Forms.DataVisualization.Charting.ChartArea.RecalculateAxesScale()
[РЕДАКТИРОВАТЬ 2]
Пример списка:
List<double> dblList = new List<double>();
dblList.Add(0.0);
dblList.Add(-7.4876421623346545E-36);
dblList.Add(1.0);
dblList.Add(-26697097281536.0);
dblList.Add(-6.8163553952838136E+28); //problem!!!!!
Последнее значение создает проблему (красный крест без исключения). Таким образом, кажется, что минимальное и максимальное значения для преобразования списка не подходят. Есть идеи по этому поводу?
double min = (double)Decimal.MinValue; //min = -7.9228162514264338E+28
double max = (double)Decimal.MaxValue; //max = 7.9228162514264338E+28
2 ответа
Произошла ошибка в RecalculateAxesScale (System.OverflowException: значение было слишком большим или слишком маленьким для десятичного числа) из-за ошибки в библиотеке. Он использует десятичные значения внутри реализации функций диаграммы (особенно в пересчете / увеличении осей), что вызывает проблему.
Просто проверяя каждую точку графика, является ли ее значение ниже или больше
double min = (double)Decimal.MinValue;
double max = (double)Decimal.MaxValue;
и заменить его на эти значения не решили проблему.
Я выбрал -/+7.92E+27
в качестве границ вместо вышеупомянутых, и теперь все работает нормально.
Таким образом, предлагаемое решение на данный момент является почти, но не совсем правильным. Если бы это был открытый исходный код, я мог бы найти решение проблемы напрямую, но, увы, я должен только догадываться о фактической реализации. Библиотека диаграмм преобразуется в десятичную и выдает исключение при превышении диапазона значений при преобразовании из двойного. Очевидное решение проверки всех значений вне допустимого диапазона и установки значений Decimal.MinValue и Decimal.MaxValue завершается неудачно с тем же исключением. Фактически, фактические максимальные и минимальные значения, разрешенные механизмом построения диаграмм, были найдены мною в результате некоторых экспериментов примерно на порядок меньше.
Достаточно обсуждения, вот мой рабочий исходный код для диаграммы TVQ с иногда превышающими границы двойными значениями. Максимальные и минимальные значения графика предварительно рассчитаны для эффективности. Замените все вызовы AddXY на SafeChartDouble. Измените тип данных AxisX, если это необходимо для вашего приложения.
private static readonly double SCALE_FACTOR = 10;
private static readonly double MIN_CHART_VALUE
= Convert.ToDouble(Decimal.MinValue) / SCALE_FACTOR;
private static readonly double MAX_CHART_VALUE
= Convert.ToDouble(Decimal.MaxValue) / SCALE_FACTOR;
private void SafeChartDouble(Series cs, DateTime ts, double dv)
{
// microsoft chart component breaks on very large/small values
double chartv;
if (dv < MIN_CHART_VALUE)
{
chartv = MIN_CHART_VALUE;
}
else if (dv > MAX_CHART_VALUE)
{
chartv = MAX_CHART_VALUE;
}
else
{
chartv = dv;
}
cs.Points.AddXY(ts, chartv);
}