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();
}

[EDIT]

Тип списка 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!!!!!
Последнее значение порождает проблему (Красный Крест без исключения). Таким образом, кажется, что значения min и max для преобразования списка не подходят. Есть какие-нибудь идеи на этот счет?
 double min = (double)Decimal.MinValue; //min = -7.9228162514264338E+28
 double max = (double)Decimal.MaxValue; //max =  7.9228162514264338E+28
2 2

2 ответа:

Ошибка в RecalculateAxesScale (System.OverflowException: значение было либо слишком большим, либо слишком маленьким для десятичной дроби) был выброшен из-за ошибки в библиотеке. Он использует десятичные значения внутри реализации функций диаграммы (особенно в пересчете осей/масштабировании), что вызывает проблему.

Просто проверяет для каждой точки диаграммы, если ее значение меньше или больше, чем

double min = (double)Decimal.MinValue;
double max = (double)Decimal.MaxValue;

И заменить его на эти значения не решило проблему.

Я выбрал -/+7.92E+27 в качестве границ вместо тех, что выше, и теперь все работает нормально.

Таким образом, предложенное до сих пор решение почти, но не совсем верно. Если бы это был открытый исходный код, я мог бы найти решение проблемы напрямую, но, увы, я должен только догадываться о фактической реализации. Библиотека диаграмм, по-видимому, преобразуется в десятичную и выдает исключение, когда диапазон значений превышен при преобразовании из double. Очевидное решение проверки всех значений вне диапазона и установки в десятичное число.Минвал и десятичное число.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);
    }