3

我有一个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
4

2 回答 2

2

由于库中的错误,引发了 RecalculateAxesScale 中的错误 (System.OverflowException: Value is either too large or too small for a Decimal)。它在图表函数的实现中使用十进制值(尤其是在轴重新计算/缩放中),这会导致问题。

只需检查每个图表点的值是否低于或大于

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

并用这个值替换它并没有解决问题。

我选择了-/+7.92E+27边界而不是上面的边界,现在一切正常。

于 2013-06-26T07:42:16.047 回答
1

因此,到目前为止所提供的解决方案几乎是正确的,但并不完全正确。如果它是开源的,我可以直接找到解决问题的方法,但可惜我只能推测实际的实现。图表库似乎转换为十进制,并在从 double 转换时超出值范围时引发异常。检查所有超出范围的值并设置为 Decimal.MinValue 和 Decimal.MaxValue 的明显解决方案失败并出现相同的异常。事实上,图表引擎允许的实际最大值和最小值是我自己通过一些实验发现的,大约要小一个数量级。

足够的讨论,这是我的 TVQ 图表的工作源代码,有时会超出双精度值。为了提高效率,预先计算了最大值和最小值图表值。用 SafeChartDouble 替换对 AddXY 的所有调用。根据应用程序的需要更改 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);
    }
于 2014-11-20T00:38:26.673 回答