0

I've implemented a User Control class to extend the functionality of the Chart class. This chart will have data added to it in real time. The User Control class creates a ChartArea, and adds it to the underlying chart. It also adds a Title, Legend and Series. My problem is when I add new data points to the chart series, the chart does not update to reflect this as it does in the vanilla Chart.

The User Control class contains a sub to add data to the underlying chart:

Chart1.Series(seriesName).Points.AddXY(xValue, yValue)

I've mocked up a data source and can verify there are indeed data points in the series. I've tried calling invalidate(), refresh(), and/or update() on Chart1, the ChartArea, the Series, and the User Control class itself. I also added data points to the Series as soon as it was created, which did not appear either.

I feel I'm missing something simple; why do these data points not appear?

Relevant code:

(dataChart is the Chart associated with the User Control)

Imports System.Windows.Forms.DataVisualization.Charting

Public Class ScrollChart
    Private _legendName As String = "defaultLegend"

    Private _chartSpan As Single = 10
    Private _xAxisFormat As String = "#.0"
    Private _yAxisFormat As String = "#.0"
    Private _xMajorInterval As Single = 1
    Private _xMinorInterval As Single = 0.5

    '...Property getters and setters omitted

    Public Sub New()
        ' This call is required by the designer.
        InitializeComponent()

        'Remove default chart objects
        dataChart.Legends.Clear()
        dataChart.Titles.Clear()
        dataChart.Annotations.Clear()
        dataChart.Series.Clear()
        dataChart.ChartAreas.Clear()
    End Sub

    Public Sub createChartArea(ByVal areaName As String, ByVal areaTitle As String, ByVal xAxisTitle As String, ByVal yAxisTitle As String)
        'Create new ChartArea
        Dim newArea As ChartArea = New ChartArea(areaName)

        'Add area title
        Dim chartTitle As Title = New Title(areaTitle)
        dataChart.Titles.Add(chartTitle)

        'Add area legend
        Dim areaLegend As Legend = New Legend(_legendName)
        areaLegend.Docking = Docking.Bottom
        dataChart.Legends.Add(areaLegend)

        'Set X axis defaults for scrolling
        newArea.AxisX.Minimum = 0
        newArea.AxisX.Maximum = _chartSpan
        newArea.AxisX.MajorGrid.Interval = _xMajorInterval
        newArea.AxisX.MinorGrid.Enabled = True
        newArea.AxisX.MinorGrid.Interval = _xMinorInterval
        newArea.AxisX.LabelStyle.Format = _xAxisFormat
        newArea.AxisX.IsStartedFromZero = False
        newArea.AxisX.Title = xAxisTitle

        'Set Y axis defaults for scrolling
        newArea.AxisY.Minimum = 0
        newArea.AxisY.Maximum = 1
        newArea.AxisY.MinorGrid.Enabled = True
        newArea.AxisY.LabelStyle.Format = _yAxisFormat
        newArea.AxisY.IsStartedFromZero = False
        newArea.AxisY.Title = yAxisTitle

        'Add to chart
        dataChart.ChartAreas.Add(newArea)
    End Sub

    Public Sub createChartSeries(ByVal areaName As String, ByVal seriesName As String, ByVal seriesTitle As String)
        'Create new Series
        Dim newSeries As Series = New Series(seriesName)

        'Add series legend
        newSeries.Legend = _legendName
        newSeries.LegendText = seriesTitle

        'Set defaults for scrolling
        newSeries.ChartType = SeriesChartType.Line
        newSeries.Color = Color.Red
        newSeries.ChartArea = areaName
        newSeries.MarkerColor = Color.Red

        'Add to chart
        dataChart.Series.Add(newSeries)
    End Sub

    Public Sub addData(ByVal seriesName As String, ByVal xValue As Single, ByVal yValue As Single)
        'Add new data point
        dataChart.Series(seriesName).Points.AddXY(xValue, yValue)

        'Remove oldest point if series is larger than the given chart span
        Dim newestX As Double = dataChart.Series(seriesName).Points.Last.XValue
        Dim oldestX As Double = dataChart.Series(seriesName).Points.First.XValue

        If ((newestX - oldestX) > _chartSpan) Then
            dataChart.Series(seriesName).Points.RemoveAt(0)
        End If

        'Redraw axis
        dataChart.ChartAreas(dataChart.Series(seriesName).ChartArea).RecalculateAxesScale()
    End Sub

    Private Sub ScrollChart_Resize(sender As Object, e As EventArgs) Handles Me.Resize
        'Resize chart to control size
        dataChart.Size = Size
    End Sub
End Class

Class usage in the testing form:

Public Class Form1
    Private dataSource As New MockDataSource(10, 0.5)
    Private startTime As Date = Date.Now

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ScrollChart1.createChartArea("area1", "Test Data", "Time (Seconds)", "Value (Unitless)")
        ScrollChart1.createChartSeries("area1", "series1", "Test Value")
    End Sub

    Private Sub pollTimer_Tick(sender As Object, e As EventArgs) Handles pollTimer.Tick
        Dim currentElapsed As Single = CSng((Date.Now - startTime).TotalSeconds)

        ScrollChart1.addData("series1", currentElapsed, dataSource.getRandomValue)
    End Sub
End Class
  • You indicate that you create a new `ChartArea`. Did you remember to set the `Series.ChartArea` property to point to that new `ChartArea`? It would help if you posted some code so that we do not need to make blind guesses of what could possibly be wrong. – TnTinMn Aug 09 '17 at 20:48
  • Sorry, I was worried about including too much code; but I suppose too little is worse. Question edited to include code. – Sean Martin Aug 09 '17 at 21:21
  • Still more confusing. If the `ChartArea` property of the default `Series` is set to the `ChartArea` I create in my class, it works. If the `ChartArea` property of the `Series` I create in my class is set to the default `ChartArea`, it also works. The `Series` and `ChartArea` I create in my class won't work together, but they will work with the default versions. – Sean Martin Aug 09 '17 at 22:54
  • I have used your code to create the UC and it displays the values fine. You have some work to do on the X-Axis update code. Start off letting it autoscale by not setting the Min/Max values. Once you get your data displaying, you can work on your logic. – TnTinMn Aug 09 '17 at 23:20

0 Answers0