【问题标题】:WPF Toolkit Chart - NullReferenceException after Series.Clear()WPF 工具包图表 - Series.Clear() 之后的 NullReferenceException
【发布时间】:2013-03-12 14:41:34
【问题描述】:

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

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

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

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

我用Data Visualization Development Releases 4.0

【问题讨论】:

标签: c# wpf charts wpftoolkit


【解决方案1】:

我想我已经找到了这个错误的原因。在删除它们之前,您应该从每个系列中删除 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 类中添加这个方法而不需要反射,那么它将在没有开销的情况下执行。

【讨论】:

  • 我已经试过了。越来越好了,但是如果我点击修改-点击的速度足够快,同样的错误又会出现。
  • @hansmaad 我更新了答案。您应该使用从图表数据点中清除事件的私有方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 1970-01-01
  • 2013-03-16
  • 1970-01-01
  • 1970-01-01
  • 2011-04-09
相关资源
最近更新 更多