Go Back  Xtreme Visual Basic Talk > Visual Basic .NET (2002/2003/2005/2008, including Express editions) > .NET General > How to control graph intervals


Reply
 
Thread Tools Display Modes
  #1  
Old 12-10-2010, 04:30 PM
Michael___ Michael___ is offline
Centurion
 
Join Date: Sep 2009
Posts: 111
Default How to control graph intervals


I'm using the chart control that's built in to Visual Basic 2010.NET Service Pack 4.

I am creating a basic date time graph with time on the axis and, at the minute, random points between -20 and positive 20 on the y axis. At the minute I can set everything up perfectly. The only problem is that the label on the x axis is not a time, it's a number. To be precise, it's the XLabelInterval value. This value is a double, so the label on the x axis is also a double not a time. But that's only interval I am setting. I think, by default, because I am not setting any labels, it is just using that value as the label as well.

Here is some variables I declare, for controlling my graph
Code:
SuitableXReadingFrequency = Screen.PrimaryScreen.Bounds.Width / 60
XMin = CustomizeGraph_frm.DateFrom_dtp.Value.AddHours(CustomizeGraph_frm.TimeFrom_dtp.Value.Hour).AddMinutes(CustomizeGraph_frm.TimeFrom_dtp.Value.Minute)
        XMax = CustomizeGraph_frm.DateTo_dtp.Value.AddHours(CustomizeGraph_frm.TimeTo_dtp.Value.Hour).AddMinutes(CustomizeGraph_frm.TimeTo_dtp.Value.Minute)
        XRange = DateDiff(DateInterval.Minute, XMin, XMax)
        XInterval = CustomizeGraph_frm.ReadingFrequency(CustomizeGraph_frm.ReadingFrequency_cmb.SelectedIndex)
        XLabelInterval = Math.Ceiling(XRange / SuitableXReadingFrequency / XInterval)
I set the interval of each piont on the graph to one. So everything is relative to that. i.e how many labels are there between each point.

I want the x axis labels to be, say, every 15 minutes.
So 0:15, 0:30, 0:45, 1:00, 1:15, 1:30... 14:30... 17:00 ect..

Instead it showing the XAxisLabelInterval value.
So 1, 5, 9, 13, 17, 21

I want there to be 1 label between every 4 points on the grapg. Not set the label to increment by four. Although, my code does actually set the label interval correctly, but it also changes the interval label text. Thus, I think I need a way of setting the interval label text on the x axis. Is there a way, How do I do it? Just there has gotta be a way.

I found this code which, I think, is what I'm looking for, but it doesn't work.
Code:
Imports System.Windows.Forms.DataVisualization.Charting
...

Dim element As Integer

' Set X axis custom labels
Dim element As Integer = Chart1.ChartAreas("Default").AxisY.CustomLabels.Add(0, 30, "Low")
element = Chart1.ChartAreas("Default").AxisY.CustomLabels.Add(30, 70, "Medium")
element = Chart1.ChartAreas("Default").AxisY.CustomLabels.Add(70, 100, "High")

' Set Y axis custom labels
element = Chart1.ChartAreas("Default").AxisX.CustomLabels.Add(0.5, 1.5, "Jan")
Chart1.ChartAreas("Default").AxisX.CustomLabels(element).GridTicks = GridTickTypes.All 

element = Chart1.ChartAreas("Default").AxisX.CustomLabels.Add(1.5, 2.5, "Feb")
Chart1.ChartAreas("Default").AxisX.CustomLabels(element).GridTicks = GridTickTypes.TickMark 

element = Chart1.ChartAreas("Default").AxisX.CustomLabels.Add(2.5, 3.5, "Mar")
Chart1.ChartAreas("Default").AxisX.CustomLabels(element).GridTicks = GridTickTypes.All 

element = Chart1.ChartAreas("Default").AxisX.CustomLabels.Add(3.5, 4.5, "Apr")
Chart1.ChartAreas("Default").AxisX.CustomLabels(element).GridTicks = GridTickTypes.TickMark 

element = Chart1.ChartAreas("Default").AxisX.CustomLabels.Add(4.5, 5.5, "May")
Chart1.ChartAreas("Default").AxisX.CustomLabels(element).GridTicks = GridTickTypes.All 

' set second row of labels
Chart1.ChartAreas("Default").AxisX.CustomLabels.Add(0.5, 3.5, "Q1", 1, LabelMarkStyle.LineSideMark)
Chart1.ChartAreas("Default").AxisX.CustomLabels.Add(3.5, 5.5, "Q2", 1, LabelMarkStyle.LineSideMark)

' One more row of labels
Chart1.ChartAreas("Default").AxisX.CustomLabels.Add(0.5, 5.5, "Year 2006", 2, LabelMarkStyle.LineSideMark)
...
I got it from Microsoft in a pack with a load of other code.
I hope someone understands. I also understand that the chart control isn't the most widely ranged thing in VB.net (I could find any tutorials on it anywhere!!!!!!!!)

Thanks.
Reply With Quote
  #2  
Old 12-10-2010, 06:11 PM
AtmaWeapon's Avatar
AtmaWeapon AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

I took on the challenge because I wanted to make a small correction and felt it'd be mean to do that and not answer your question. There's no Service Pack 4.0 for VS 2010. There's not even a Service Pack 1 yet; the beta for that's due some time next year. VS 2010 lets you develop with the .NET Framework 4.0, that's probably where you're getting it from. (I mainly wanted to correct it so someone doesn't go on a wild goose chase thinking that one of your examples doesn't work because they don't have a service pack that doesn't exist.)

I agree, learning about the chart control is a real pain. It's a very complicated control in a huge namespace. They shoved it in a tab way down on the toolbox and I think few people are even aware it exists. It certainly doesn't help that the web searches I tried didn't get me to the documentation. When I did find the documentation, it isn't listing the types of high-level concept topics that give a jump-start into the API. So I had to roll up my sleeves and read the documentation. This kind of junk ticks me off so I think my new free time project is going to be to learn more about this control. That'll take a while so let's get to examining specifics. (For the record, it's not all Microsoft's fault. It's hard to give a control this many features without making it really hard to understand.)

The He-Man reference documentation starts here. Somehow I found my way to this blog and the Getting Started guides; that's when I started making real progress.

I didn't understand a lot of your post but I'll lay out the scenario as I understand it. Your test data consists of DateTime X values and random Y values. The only important part of the DateTime values is the time. You want the X axis labels to be 0, 0:15, 0:30, etc. I managed to pull this off without much code. Here's what I did.

First, I spent about 45 minutes just playing with the API. I fiddled with properties to see what they did and tried to find a solution to the problem by myself. It didn't end very well and I caused some interesting but bad things to happen. I knew the series's XValueType needed to be DateTime, but weird stuff happened as I played with IntervalType and Interval. So I dug into the documentation.

The labels topic had some interesting information about custom labels, but it seemed like this was for weird labels like "Muskrats" that aren't really a formatting step away from a double; it also felt too painful for what I felt should be a main scenario. I noticed the Axis.LabelStyle.Format property and filed it away for later; I felt like this was a dead end. However, it did link to Working with date and time values at run time, which gave me the information I was missing. Here's the way I see it.

If you want to display time in a sane way, you have to do a few things.
  • Your series's XValueType property must be set to ChartValueType.Time.
  • When you add the DateTime data to the series's Points, you must use the DateTime.ToOADate() method to convert the DateTime into a Double. (This is probably some implementation detail of the chart control showing through; leaky abstractions suck.)
That gets proper date and time data into the series; you have a few choices for getting the axis to display it properly.

The technique I favored was to use the axis's LabelStyle to set a format for the value (the Format property, of course.) The format string "H:mm" will format times such that midnight is 0:00, ten fifteen is 10:15, one thirty is 13:30, and so forth. This is the technique I used in the example below and I felt it was the easiest. You could also have set the axis's IntervalType to something like DateTimeIntervalType.Minutes and the Interval to 15; that puts a tick mark at every 15 minutes. I believe there's reasons to use the interval in addition to or instead of the label format, but I haven't spent enough time on the issue to determine that reason.

Here's the example I tested with; drop a chart and a button on a form and paste this in:
Code:
Imports System.Windows.Forms.DataVisualization.Charting

Public Class Form1

    Private Shared ReadOnly RNG As New Random()

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim series As Series = _chart.Series(0)
        Dim chartArea As ChartArea = _chart.ChartAreas(0)
        Dim xAxis As Axis = chartArea.AxisX

        series.XValueType = ChartValueType.Time
        AddData(series)
        series.ChartType = SeriesChartType.Line

        xAxis.LabelStyle.Format = "H:mm"
    End Sub

    Private Sub AddData(ByVal series As Series)
        Dim baseTime As DateTime = New DateTime(2010, 12, 10, 0, 0, 0)
        For i As Integer = 1 To 10
            series.Points.AddXY(baseTime.ToOADate(), RNG.Next(-20, 20))
            baseTime = baseTime.AddMinutes(15)
        Next
    End Sub

End Class
Does that get you close to what you want? If not, please explain what's lacking.
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #3  
Old 12-11-2010, 04:14 AM
jo0ls jo0ls is offline
Senior Contributor

Forum Leader
* Expert *
 
Join Date: Feb 2005
Location: London
Posts: 1,050
Default

Quote:
Originally Posted by AtmaWeapon View Post
=There's no Service Pack 4.0 for VS 2010. There's not even a Service Pack 1 yet; the beta for that's due some time next year.
It's a bit ahead of schedule.

Last edited by jo0ls; 12-11-2010 at 04:29 AM.
Reply With Quote
  #4  
Old 12-11-2010, 07:04 AM
Michael___ Michael___ is offline
Centurion
 
Join Date: Sep 2009
Posts: 111
Default

Yeah, sorry about the confusion with the Service Pack. I meant Framework 4.0.
Secondly, it gets me a lot closer to what I am after. At the minute, it displays an actual time. Except, it only displays it once, at the beginning of the X axis and doesn't show the interval between each one. Also, there are no tick marks.
Do I need to use something like this?
Code:
TheChart_cht.ChartAreas("ChartArea").AxisX.CustomLabels.Add(10, 10, "Label", 10, LabelMarkStyle.LineSideMark)
For each label that is. Should I put it in a loop?

Here's the link to the Microsoft website, where I got the code from. You may have seen it already:
http://code.msdn.microsoft.com/mscha...ReleaseId=4418

Finally, I use a long bit of code to add the tickmarks and background to the graph. You see, the user can select either no grid, plain grid or graphic grid. That's why it's quite long. The code I use to make these is this:
Code:
TheChart_cht.ChartAreas("ChartArea").BackColor = CustomizeGraph_frm.BackgroundColor_pnl.BackColor
            TheChart_cht.ChartAreas("ChartArea").AxisX.LabelStyle.Format = "HH:mm"

            If CustomizeGraph_frm.NoGrid_rdo.Checked Then
                TheChart_cht.ChartAreas("ChartArea").AxisX.MajorGrid.Enabled = False
                TheChart_cht.ChartAreas("ChartArea").AxisY.MajorGrid.Enabled = False
            End If
            If CustomizeGraph_frm.NoGrid_rdo.Checked Or CustomizeGraph_frm.PlainGrid_rdo.Checked Or CustomizeGraph_frm.GraphicalGrid_rdo.Checked Then
                TheChart_cht.ChartAreas("ChartArea").AxisX.LineWidth = CustomizeGraph_frm.AxisThickness_cmb.SelectedIndex * 2 + 1
                TheChart_cht.ChartAreas("ChartArea").AxisX.LineColor = CustomizeGraph_frm.AxisColor_pnl.BackColor
                TheChart_cht.ChartAreas("ChartArea").AxisX.MajorTickMark.Interval = XLabelInterval
                TheChart_cht.ChartAreas("ChartArea").AxisX.LabelStyle.Interval = XLabelInterval
                TheChart_cht.ChartAreas("ChartArea").AxisX.MajorTickMark.LineDashStyle = ChartDashStyle.Solid
                TheChart_cht.ChartAreas("ChartArea").AxisX.MajorTickMark.LineWidth = 2
                TheChart_cht.ChartAreas("ChartArea").AxisX.MajorTickMark.Size = 1.6
                TheChart_cht.ChartAreas("ChartArea").AxisX.MinorTickMark.Enabled = True
                TheChart_cht.ChartAreas("ChartArea").AxisX.MinorTickMark.Interval = 1
                TheChart_cht.ChartAreas("ChartArea").AxisX.MinorTickMark.Size = 1.08

                TheChart_cht.ChartAreas("ChartArea").AxisY.LineWidth = CustomizeGraph_frm.AxisThickness_cmb.SelectedIndex * 2 + 1
                TheChart_cht.ChartAreas("ChartArea").AxisY.LineColor = CustomizeGraph_frm.AxisColor_pnl.BackColor
                TheChart_cht.ChartAreas("ChartArea").AxisY.MajorTickMark.Interval = YLabelInterval
                TheChart_cht.ChartAreas("ChartArea").AxisY.LabelStyle.Interval = YLabelInterval
                TheChart_cht.ChartAreas("ChartArea").AxisY.MajorTickMark.LineDashStyle = ChartDashStyle.Solid
                TheChart_cht.ChartAreas("ChartArea").AxisY.MajorTickMark.LineWidth = 2
                TheChart_cht.ChartAreas("ChartArea").AxisY.MajorTickMark.Size = 1
                TheChart_cht.ChartAreas("ChartArea").AxisY.MinorTickMark.Enabled = True
                TheChart_cht.ChartAreas("ChartArea").AxisY.MinorTickMark.Interval = 1
                TheChart_cht.ChartAreas("ChartArea").AxisY.MinorTickMark.Size = 0.6

            End If
            If CustomizeGraph_frm.PlainGrid_rdo.Checked Or CustomizeGraph_frm.GraphicalGrid_rdo.Checked Then
                TheChart_cht.ChartAreas("ChartArea").AxisX.MinorGrid.LineColor = CustomizeGraph_frm.GridColor_pnl.BackColor
                TheChart_cht.ChartAreas("ChartArea").AxisX.MajorGrid.LineColor = CustomizeGraph_frm.GridColor_pnl.BackColor
                TheChart_cht.ChartAreas("ChartArea").AxisX.MinorGrid.Enabled = True
                TheChart_cht.ChartAreas("ChartArea").AxisX.MinorGrid.LineWidth = 1
                TheChart_cht.ChartAreas("ChartArea").AxisX.MajorGrid.LineWidth = 1
                TheChart_cht.ChartAreas("ChartArea").AxisX.MinorGrid.Interval = XLabelInterval
                TheChart_cht.ChartAreas("ChartArea").AxisX.MajorGrid.Interval = XLabelInterval

                TheChart_cht.ChartAreas("ChartArea").AxisY.MinorGrid.LineColor = CustomizeGraph_frm.GridColor_pnl.BackColor
                TheChart_cht.ChartAreas("ChartArea").AxisY.MajorGrid.LineColor = CustomizeGraph_frm.GridColor_pnl.BackColor
                TheChart_cht.ChartAreas("ChartArea").AxisY.MinorGrid.Enabled = True
                TheChart_cht.ChartAreas("ChartArea").AxisY.MinorGrid.LineWidth = 1
                TheChart_cht.ChartAreas("ChartArea").AxisY.MajorGrid.LineWidth = 1
                TheChart_cht.ChartAreas("ChartArea").AxisY.MinorGrid.Interval = 1
                TheChart_cht.ChartAreas("ChartArea").AxisY.MajorGrid.Interval = YLabelInterval
            End If
            If CustomizeGraph_frm.GraphicalGrid_rdo.Checked Then
                TheChart_cht.ChartAreas("ChartArea").AxisX.MinorGrid.LineColor = CustomizeGraph_frm.GridColor_pnl.BackColor
                TheChart_cht.ChartAreas("ChartArea").AxisX.MajorGrid.LineWidth = 2

                TheChart_cht.ChartAreas("ChartArea").AxisY.MinorGrid.LineColor = CustomizeGraph_frm.GridColor_pnl.BackColor
                TheChart_cht.ChartAreas("ChartArea").AxisY.MajorGrid.LineWidth = 2
            End If
It's just a lot of all of the declerations you can make. Perhaps it's this part that I'm doing wrong, as there are no tickmarks or labels on the X axis, except the first one.
Reply With Quote
  #5  
Old 12-11-2010, 07:39 AM
AtmaWeapon's Avatar
AtmaWeapon AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

Huh, maybe I have SP1 confused with Silverlight 5; I know that one's way out.

Michael__, did you use my code directly in a new project? I spent an hour putting that tiny bit of code together and wouldn't have posted it if it didn't have a label at each interval when I ran it. I just double-checked it and it worked perfectly, though I forgot you have to name the chart "_chart" or modify that variable.

If you instead tried to directly integrate it into your project, there's a myriad of things that could be causing the behavior. There's actually 2 "rows" of labels on each axis. The first row has the auto-generated labels; if you add a custom label to that row then all of the auto-generated labels are removed and only custom labels you add are displayed. So you may have some remnant of experimenting with custom labels hanging around, or there may be something else entirely causing the problem.

I'm afraid I don't have enough of your code to know for sure what's causing the problem. It takes a lot of code to configure a graph and since I'm just learning about the control I don't have the experience to associate "this bad thing is happening" with common causes. I'm afraid I can't help much more than to say "My example worked for me" unless you can post a version of your project that demonstrates the problem (you can omit anything unrelated to the graph) or a smaller project that does the same thing.
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #6  
Old 12-11-2010, 09:47 AM
Michael___ Michael___ is offline
Centurion
 
Join Date: Sep 2009
Posts: 111
Default

I did try intergrating your code, but, it's now apparent, I don't have enough experience with graphs or charts. Consequently, I will use your code as the building blocks. I am currently just using your code and it generates a line graph. So, I will add my code now.

Last edited by Michael___; 12-11-2010 at 11:06 AM.
Reply With Quote
  #7  
Old 12-11-2010, 11:28 AM
Michael___ Michael___ is offline
Centurion
 
Join Date: Sep 2009
Posts: 111
Default

It was a lot easy than I first thought. The graph now shows the date. The reason it wasn't working before was because of I was trying to give the XLabelInterval a value. IF I don't assign it a values, then it works. But that, quite ironically, is also the problem. If I leave it as it is, I can't change the number of labels on the X axis. It will always be automatic. This is even more of a problem because I wanted to give the user the control of selecting this themselves.

Let's say:
The amount of X axis labels needed is 24. One for every hour of a day.
The amount of data plotted on the graph is 96 points. One every 15 minutes.
So the XInterval equals 15 and the XRange = 1440.
So do I need to plot the X axis labels every 60 points or every 4 points? Either one doesn't work. In fact, I've tried a lot of numbers and I can't set the interval of the labels on the X axis. Any ideas.

By the way, thanks for that code. It's helped me restructure my program a lot so it looks a lot neater. Thanks.
Reply With Quote
  #8  
Old 12-15-2010, 10:15 AM
Michael___ Michael___ is offline
Centurion
 
Join Date: Sep 2009
Posts: 111
Default

I still can't select the x label interval. I also noticed that in AtmaWeapon's example, you can't change the X label frequency. I have now changed my code because I made something that works better:
Code:
For i = 0 To CustomizeGraph_frm.ReadingFrequency.Length - 1 Step 1
                Select Case i
                    Case 0 To 9
                        XLabelUnit = "Minutes"
                        If DateDiff(DateInterval.Minute, XMinimum, XMaximum) / CustomizeGraph_frm.ReadingFrequency(i) <= SuitableXReadingFrequency Then
                            XLabelInterval = Date.FromOADate(CustomizeGraph_frm.ReadingFrequency(i))
                            Exit For
                        End If
                    Case 10 To 14
                        XLabelUnit = "Days"
                        If DateDiff(DateInterval.Day, XMinimum, XMaximum) / CustomizeGraph_frm.ReadingFrequency(i) <= SuitableXReadingFrequency Then
                            XLabelInterval = Date.FromOADate(CustomizeGraph_frm.ReadingFrequency(i))
                            Exit For
                        End If
                    Case 15 To 18
                        XLabelUnit = "Month"
                        If DateDiff(DateInterval.Month, XMinimum, XMaximum) / CustomizeGraph_frm.ReadingFrequency(i) <= SuitableXReadingFrequency Then
                            XLabelInterval = Date.FromOADate(CustomizeGraph_frm.ReadingFrequency(i))
                            Exit For
                        End If
                    Case 19 To 23
                        XLabelUnit = "Years"
                        If DateDiff(DateInterval.Year, XMinimum, XMaximum) / CustomizeGraph_frm.ReadingFrequency(i) <= SuitableXReadingFrequency Then
                            XLabelInterval = Date.FromOADate(CustomizeGraph_frm.ReadingFrequency(i))
                            Exit For
                        End If
                End Select
            Next
As you can see, instead of setting the XRange variable, and checking to see if that if higher or lower than a certain point, I use the DateDifference function to find the difference depending on the XUnit. This is because months can have 28, 29, 30 and 31 days. They are not like days. For days you can say it has 1440 minutes. You can't for months. I still use: XLabelInterval.ToOADate to set the XLabel.Interval, but one thing I noticed was, if you dates get larger, it starts plotting the labels. If they are small intervals like 15 minutes, it doesn't show anything. If they are bigger intervals like 440 minutes, they don't show the labels, but the tickmarkers are visible. If they are really big dates, like 2 days, then the labels start to appear.

Is there an explanation? I don't think I'm setting the X label intervals too high because it is only like 1 and they still don't appear? If you have any questions, just ask. Thanks.
Reply With Quote
  #9  
Old 12-30-2010, 06:13 AM
Michael___ Michael___ is offline
Centurion
 
Join Date: Sep 2009
Posts: 111
Default

I just want to say something. AtmaWeapon, your code doesn't let me select the X axis label interval, just in case I didn't make that clear. At no point do you declare a variable called XLabelInterval (or something along those lines). That's what I am trying to achieve.
Reply With Quote
Reply

Tags
aardvarks, chart, control, date, graph, time, vague tags


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
 
 
-->