3

该错误发生在更复杂的上下文中,但可以在这个简单的示例中重现:

主窗口.xaml

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

主窗口.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);
    }
}

单击清除,然后单击修改。清除从图表中删除系列并创建一个新系列。Modify 修改系列绑定的源。UpdateDataPoint我得到 NullReferenceException的已删除系列调用ActualDependentRangeAxis为空:

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

我使用数据可视化开发版本 4.0

4

1 回答 1

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- 事件将按原样取消订阅。

编辑

如果您快速单击“修改”按钮,然后立即单击“清除”按钮,它会在一种情况下崩溃。发生这种情况是因为图表需要一些时间来取消订阅事件中的数据点并隐藏它们。

无论如何,您可以手动取消订阅,但您必须使用反射,因为必要的方法 (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类中而无需反射,那么它将在没有开销的情况下执行。

于 2013-03-16T13:13:18.987 回答