2013-06-20 75 views
2

我有一個treeViewelement其中每個節點代表一個雙列表。微軟圖表控制 - 失敗後重繪圖表(紅十字)

我正在使用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() 

[EDIT 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 
+0

我的答案是無用的,移動討論在這裏。值本身是確定的,但System.Decimal拋出溢出/溢出的算術運算(並忽略檢查/未檢查的要求)... –

+0

有沒有人有一個想法是什麼問題?我該如何處理?我應該用某種標準值代替太高/過低的值嗎? – purbsel

+0

是的,它可能是一個解決方案,但你也應該處理縮放(因爲它可能會導致軸重新計算)。 –

回答

2

在RecalculateAxesScale錯誤(System.OverflowException:值被太大或太小,一個十進制)被拋出,因爲庫中的Bug。它在圖表函數的實現中使用十進制值(特別是在軸重新計算/縮放中),這會導致問題。

在所有圖表點只是檢查是否其價值比

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

更低或更高,這個值替換它並沒有解決這個問題。

我選擇-/+7.92E+27作爲邊界而不是上面的,現在一切正常。

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