3
votes

If you're familiar with ASP.NET's Charting controls, the Chart object contains a number of Series objects - which are series of datapoints that can be charted. Each series can be visualized in a different way (bar or point or line) on the same chart.

I have a custom control that I use to create and remove and modify lists of Series in a UI. Upon clicking a button, the chart is created using those Series. If I try to re-display the chart, however (even with identical Series) it blows up and throws a NullReferenceException.

Here's the relevant code - I've got an object wrapping Series (because I have some custom properties in there)

public class DataSeries
{
    private Series _series = new Series();
    ... (bunch of other properties)
    public Series Series
    {
        get { return _series; }
        set { _series = value; }
    }
}

In the control itself, I store a list of these as a property(I only create the object during non-postbacks because I want the list to persist):

private static List<DataSeries> seriesList;

public List<DataSeries> ListOfSeries
    {
        get { return seriesList; }
        set { seriesList = value; }
    }

protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            seriesList = new List<DataSeries>();
        }
    }

Then I have some amalgam of controls that I can use to add new DataSeries, remove them, and modify their properties. That all works.

When they click 'Create Chart' on the page, this is the code that gets executed:

protected void refreshChart(object sender, EventArgs e)
{
    chart.Series.Clear();

        foreach (DataSeries s in seriesControl.ListOfSeries)
        {
            string propertyName = s.YAxisProperty;

            //List of data to display for this series 
            List<Sampled_Data> sampleList = Sample.GetSamplesById(s.ComponentId);

            foreach (Sampled_Data dSample in sampleList)
            {
                //GetPropertyValue returns a float associated with the propertyname
                //selected for displaying as the Y Value
                s.Series.Points.AddY(BindingLib.GetPropertyValue(dSample, propertyName));
            }
            chart.Series.Add(s.Series);
        }
    }

The first time I execute that piece of code, it works like a charm. The second time I click on the button that executes 'refreshChart,' I get a NullReferenceException because the value of 's.Series.Points' is null. And I can't create a new object of the type that the Points property is - its constructor is private or protected.

If I'm not manipulating the Points property between subsequent calls of this function, why is it becoming null?

There are maybe a few solutions I could think of - make DataSeries inherit series instead of have one - then likely I could new the Points property if the error still persists. I could also deep copy the ListOfSeries and see if that solves my problem. I could also perhaps shove all my custom attributes into the Series object - it has a customfields property (or something similarly named). If I'm not passing around an object wrapping another one, that might eliminate the issue.

Any ideas why this might be occurring and how it might be solved?

1

1 Answers

5
votes

I'm not 100% sure, but i suspect that the line

chart.Series.Clear();

directly clears the internal Series of your static member seriesList because the line

chart.Series.Add(s.Series);

just passes a reference to that Series to the chart.

I think that is not supposed to happen: you probably fill in (and clear) that member yourself somewhere else.

You could check this assumption by removing the getter:

set { seriesList = value; }

At that moment the code should throw an exception at

chart.Series.Clear();

when you refresh: the Chart isn't allowed to clear your Series in your static member seriesList anymore.

Is there a reason why you're using a static member?

Offering a deep-copy of the Series via your static member and passing that to the chart would work, if not for this answer, and the fact that unfortunately Series isn't marked as [Serializable].

// Do you want to write this Property? copying all fields of Series Manually?
chart.Series.Add(s.DeepCopyOfMySeries); 

Good Luck!