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 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.