简体   繁体   中英

WPF Toolkit Chart - NullReferenceException after Series.Clear()

The error occurs in a much more complex context, but can be reproduced in this simple example:

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

Click on Clear then click on Modify . Clear removes the series from the chart and creates a new one. Modify modifies the source for the series bindings. The removed series calls UpdateDataPoint where I get a NullReferenceException : ActualDependentRangeAxis is null:

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

I use Data Visualization Development Releases 4.0

I think I've found the cause of this error. You should remove the DataContext from each series before you delete them:

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

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

If you clear DataContext - events will be unsubscribed as it should be.

Edit

It will crash in one case if you click quickly the Modify button and then immideately the Clear button. It happens because the chart needs some time to unsubscribe data points from events and hide them.

Anyway you can unsubscribe manually, but you have to use reflexion, because the necessary methods ( DetachEventHandlersFromDataPoints and PlotArea ) are internal or private.

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

Also if you have a possibility to recompile the toolkit library, you can add this method without reflexion to the DataPointSeries class, then it will be executed without overhead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM