3

エラーははるかに複雑なコンテキストで発生しますが、次の簡単な例で再現できます。

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

[クリア]をクリックしてから、 [変更]をクリックします。Clearはチャートからシリーズを削除し、新しいシリーズを作成します。変更は、シリーズバインディングのソースを変更します。UpdateDataPointNullReferenceExceptionを取得する削除されたシリーズ呼び出し: ActualDependentRangeAxisis null:

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すると、イベントは本来のように購読解除されます。

編集

[変更]ボタンをすばやくクリックしてから、すぐに[クリア]ボタンをクリックすると、クラッシュする場合があります。これは、チャートがイベントからデータポイントのサブスクライブを解除し、それらを非表示にするのに時間がかかるために発生します。

とにかく手動で購読を解除することはできますが、必要なメソッド(DetachEventHandlersFromDataPointsおよびPlotArea)は内部またはプライベートであるため、リフレクションを使用する必要があります。

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 に答える