1
votes

using System.Web.UI.DataVisualization.Charting.Chart

My data is like so:
sample data

...but my chart does not draw lines between points of missing data:
incomplete chart

As you can see, the 2nd column has a point at 51 on 7/09/2015 and then points are empty until 7/16/2015. I want the chart to draw a line from the point at 7/09/2015 to 7/16/2015.

How can I get this to work?

This is my existing Series construction:

var series = chart.Series[header] = new Series(header) {
    BorderWidth = 2,
    ChartArea = DataTable.TableName,
    ChartType = SeriesChartType.FastLine,
    Color = legendColors[header],
    Enabled = true,
    Font = new Font("Lucida Sans Unicode", 6f),
    XValueMember = "Week",
    YValueMembers = header
};

Update 1:
With @jstreet's answer, I am now getting a line drawn. But the value is being represented as if it were 0:
incorrect empty point rendering

What is expected is the following where thick dashed lines should replace the lines representing a value of 0:
expected empty point rendering

Update 2:
Modified the for-loop to manually add DataPoints to the series following @jstreet's example for add points in code-behind:

for (int column = 0; column < seriesHeaders.Length; column++) {
    var header = seriesHeaders[column];

    var series = chart.Series[header] = new Series(header) {
        BorderWidth = 2,
        ChartArea = DataTable.TableName,
        ChartType = SeriesChartType.FastLine,
        Color = legendColors[header],
        Enabled = true,
        Font = new Font("Lucida Sans Unicode", 6f),
        XValueMember = "Week",
        YValueMembers = header
    };
    series.EmptyPointStyle.Color = legendColors[header];
    series.EmptyPointStyle.AxisLabel = "Empty";

    DataTable.Rows
        .OfType<DataRow>()
        .Select(r => (double)r[header])
        .ToList()
        .ForEach(v => {
            series.Points.Add(new DataPoint(series) {
                IsEmpty = v == Double.NaN,
                YValues = new double[] { v == Double.NaN ? 0 : v }
            });
        });

}

...chart still renders what is supposed to be an empty point as a 0 value.

Update 3:
Modified construction of DataPoints. Evidently v == Double.NaN does not evaluate properly:

DataTable.Rows
    .OfType<DataRow>()
    .Select(r => (double)r[header])
    .ToList()
    .ForEach(v => {
        var isEmpty = Double.IsNaN(v);
        var value = new double[] { v == Double.NaN ? 0 : v };

        series.Points.Add(new DataPoint() {
            IsEmpty = isEmpty,
            YValues = value
        });
    });

... and I verified the Series.Points collection:
verified series NaN point IsEmpty

2

2 Answers

4
votes

You need to define an EmptyPointStyle, as shown below:

            <asp:Series Name="Series1" ChartType="Line" XValueType="DateTime">
                <Points>
                    <asp:DataPoint XValue="42005" YValues="50" />
                    <asp:DataPoint XValue="42036" YValues="70" />
                    <asp:DataPoint XValue="42064" YValues="30" />
                    <asp:DataPoint IsEmpty="True" XValue="42095" YValues="0" />
                    <asp:DataPoint XValue="42156" YValues="60" />
                    <asp:DataPoint XValue="42186" YValues="40" />
                </Points>
                <EmptyPointStyle Color="Red" />
            </asp:Series>

Result:

enter image description here

EDIT: I can also add points using code behind:

    protected void Page_Load(object sender, EventArgs e)
    {
        Chart1.Series[0].Points.Add(new DataPoint { IsEmpty = false, XValue = DateTime.Now.AddDays(1).ToOADate(), YValues = new double[] { 50 } });
        Chart1.Series[0].Points.Add(new DataPoint { IsEmpty = false, XValue = DateTime.Now.AddDays(2).ToOADate(), YValues = new double[] { 70 } });
        Chart1.Series[0].Points.Add(new DataPoint { IsEmpty = true, XValue = DateTime.Now.AddDays(3).ToOADate(), YValues = new double[] { 0 } });
        Chart1.Series[0].Points.Add(new DataPoint { IsEmpty = false, XValue = DateTime.Now.AddDays(4).ToOADate(), YValues = new double[] { 30 } });
        Chart1.Series[0].Points.Add(new DataPoint { IsEmpty = false, XValue = DateTime.Now.AddDays(5).ToOADate(), YValues = new double[] { 60 } });
    }

And i don't have the problem you're describing about not being able to set IsEmpty or getting 0's in your chart:

enter image description here

0
votes

Changed one line following all the updates provided:

ChartType = SeriesChartType.Line, // was FastLine

So the Series construction looks like this now:

for (int column = 0; column < seriesHeaders.Length; column++) {
    var header = seriesHeaders[column];

    var series = chart.Series[header] = new Series(header) {
        BorderWidth = 2,
        ChartArea = DataTable.TableName,
        ChartType = SeriesChartType.Line,
        Color = legendColors[header],
        Enabled = true,
        Font = new Font("Lucida Sans Unicode", 6f),
        XValueMember = "Week",
        YValueMembers = header
    };
    series.EmptyPointStyle.Color = legendColors[header];
    series.EmptyPointStyle.BorderWidth = 2;

    DataTable.Rows
        .OfType<DataRow>()
        .Select(r => {
            var value = (double)r[header];

            return new {
                isEmpty = Double.IsNaN(value),
                yValue = new double[] { value },
                xValue = DateTime.Parse(r["Week"].ToString()).ToOADate()
            };
        })
        .ToList()
        .ForEach(dp => {
            var dataPoint = new DataPoint() {
                IsEmpty = dp.isEmpty,
                YValues = dp.yValue,
                XValue = dp.xValue
            };

            series.Points.Add(dataPoint);
        });

}  

The chart is properly rendered:
properly rendered chart