2013-03-12 77 views
3

在一個更復雜的上下文將出現錯誤,但可在這個簡單的例子被再現:WPF工具包圖表 - Series.Clear後的NullReferenceException()

MainWindow.xaml

<Window> 
    <StackPanel> 
    <Button Click="Button_Click_1">Clear</Button> 
    <Button Click="Button_Click_2">Modify</Button> 
    <charting:Chart x:Name="chart" /> 
    </StackPanel> 
</Window> 

MainWindow.xaml的.cs

public partial class MainWindow : Window 
{ 
    Random rand = new Random(); 
    ObservableCollection<KeyValuePair<double, double>> values = 
     new ObservableCollection<KeyValuePair<double, double>>(); 

    public MainWindow() 
    { 
     InitializeComponent(); 
     values.Add(new KeyValuePair<double, double>(10, 10)); 
     values.Add(new KeyValuePair<double, double>(20, 40)); 
     values.Add(new KeyValuePair<double, double>(30, 90)); 
     values.Add(new KeyValuePair<double, double>(40, 160)); 
     values.Add(new KeyValuePair<double, double>(50, 250)); 
     AddSeries(); 
    } 

    private void Button_Click_1(object sender, RoutedEventArgs e) 
    { 
     chart.Series.Clear(); 
     AddSeries(); 
    } 

    private void AddSeries() 
    { 
     var series = new LineSeries(); 
     series.SetBinding(LineSeries.ItemsSourceProperty, new Binding()); 
     series.DataContext = values; 
     series.DependentValueBinding = new Binding("Value"); 
     series.IndependentValueBinding = new Binding("Key"); 

     chart.Series.Add(series); 
    } 

    private void Button_Click_2(object sender, RoutedEventArgs e) 
    { 
     values[3] = new KeyValuePair<double,double>(40, rand.NextDouble() * 300); 
    } 
} 

點擊清除然後點擊修改。清除從圖表中刪除系列並創建一個新系列。修改修改了系列綁定的來源。取出的一系列調用UpdateDataPoint在那裏我得到一個NullReferenceException:ActualDependentRangeAxis爲空:

protected override void UpdateDataPoint(DataPoint dataPoint) 
{ 
    double maximum = ActualDependentRangeAxis.GetPlotAreaCoordinate(
    ActualDependentRangeAxis.Range.Maximum).Value; 

我用Data Visualization Development Releases 4.0

+0

我試過你的3.5版本的代碼,一切正常。而我無法找到版本4,在codeplex上最後一個版本是3.5。 – vorrtex 2013-03-16 11:50:36

+0

從這裏開始發佈:http://blogs.msdn.com/b/delay/archive/2010/04/20/phone-y-charts-silverlight-wpf-data-visualization-development-release-4- and-windows-phone-7-charting-sample.aspx – hansmaad 2013-03-16 11:58:41

回答

2

我想我已經發現這個錯誤的原因。你應該從每個系列中刪除DataContext在刪除之前他們:

private void Button_Click_1(object sender, RoutedEventArgs e) 
{ 
    foreach (var series in chart.Series.OfType<Series>()) 
    { 
     series.DataContext = null; 
    } 

    chart.Series.Clear(); 
    AddSeries(); 
} 

如果清除DataContext - 事件將退訂理所應當的。

編輯

它將在一種情況下崩潰,如果您快速點擊修改按鈕,然後immideately清除按鈕。發生這種情況是因爲圖表需要一些時間從事件中取消訂閱數據點並隱藏它們。

無論如何,您可以手動取消訂閱,但您必須使用反射,因爲必要的方法(DetachEventHandlersFromDataPointsPlotArea)是內部或私有的。

private void Button_Click_1(object sender, RoutedEventArgs e) 
{ 
    this.DetachAllEventsFromSeries(); 

    chart.Series.Clear(); 

    AddSeries(); 
} 

private void DetachAllEventsFromSeries() 
{ 
    var plotAreaProperty = typeof(DataPointSeries).GetProperty("PlotArea", BindingFlags.Instance | BindingFlags.NonPublic); 
    var detachMethod = typeof(DataPointSeries).GetMethod("DetachEventHandlersFromDataPoints", BindingFlags.Instance | BindingFlags.NonPublic); 

    foreach (var series in chart.Series.OfType<DataPointSeries>().ToList()) 
    { 
     var plotArea = (Panel)plotAreaProperty.GetValue(series, null); 
     if (plotArea == null) 
     { 
      continue; 
     } 

     var datapoints = plotArea.Children.OfType<DataPoint>().ToList(); 
     detachMethod.Invoke(series, new[] { datapoints }); 
    } 
} 

此外,如果有可能重新編譯工具庫,你可以在不增加反射這種方法的DataPointSeries類,那麼它將被無開銷執行。

+0

我已經試過了。它越來越好,但是如果我點擊Modify-Click足夠快,則會再次發生相同的錯誤。 – hansmaad 2013-03-16 15:08:18

+0

@hansmaad我更新了答案。您應該使用從圖表數據點中清除事件的私有方法。 – vorrtex 2013-03-16 19:17:51