15

I'm currently using the charting within .NET using System.Windows.Forms.DataVisualization.Charting.Chart. Thus far it seems very powerful, and works great. However, there is a huge problem in terms of how it is auto-calculating intervals. I use a lot of double values, and in libraries like ZedGraph, it handles this perfectly. It selects min/max/interval just fine. However, in MS Chart, it may select 206.3334539832 as a minimum, and intervals of a similar decimal precision. Obviously this looks quite ugly.

So, I tried simply making the axis format {0.00} and it works great when it loads the chart. Except when you zoom in, you need greater precision, maybe at 4 decimal places instead of 2. It seems I'm either stuck with 9 decimal places all the time, or else a constant fixed number that may break when someone requires greater precision. I'd rather it pick up the precision based on the level of zoom currently applied. Libraries like ZedGraph and Dundas (which I believe MS is even using!) tend to pick good values that change as you zoom in and out.

Is there any way to have the intervals change precision as the zoom frame changes? It's probably some simple property I have set wrong, but it's hard to tell with the millions of properties this thing has (especially when there's about 14 places that represent the concept of Interval).

drharris
  • 11,194
  • 5
  • 43
  • 56
  • 2
    AFAIK, the Charting controls are based on Dundas controls. Microsoft acquired Dundas’s data visualization components some time ago. More info [here](http://blogs.msdn.com/b/bimusings/archive/2007/06/04/microsoft-acquires-dundas-s-data-visualization-components-sql-2008-news-download-ctp3.aspx) – CGK Dec 07 '10 at 15:57
  • There are no pictures in your edit? – noelicus Oct 02 '13 at 14:16
  • @noelicus Sorry, new job since then and those images were taken down at some point (apparently this was prior to SO allowing image uploads). I've removed the edit for now. I will look and see if I can find a copy of those images, and update this question if I can. – drharris Oct 07 '13 at 18:06

7 Answers7

6

I had the exact same problem when zooming. I added code to format the axis labels and call it from the Paint handler. The Axis View objects have an IsZoomed property and have functions to get the current axis limits (GetViewMinimum/Maximum). I set the Axis LabelStyle.Format to "N" for all cases unless the Max-Min=range is less than 1. Then I set the format to "F#" where # is calculated based on the axis range.

# = Convert.ToInt32(Math.Abs(Math.Log10(range) - .5)) + 1;
Kirk Woll
  • 76,112
  • 22
  • 180
  • 195
bobvt
  • 276
  • 2
  • 3
  • Thank you so much for pointing out GetViewMinimum/Maximum! These are probably the functions I was looking for. I will try this soon, and if it works for my case I will reinstate my previous bounty and give it to you. Also thanks for the code to get decimal places - after some tests in WolframAlpha it seems to generate the perfect number of decimals. – drharris Apr 13 '11 at 00:36
  • I forgot to report back, but I finally had time to spend to implement this, and it works PERFECTLY. I still think the control itself should handle this type of logic (if open source projects like ZedGraph can do it, surely MS/Dundas can). I have reinstated the original bounty on this question since this saves me a lot of headache from unhappy customers! I'll award it as soon as SO lets me. – drharris Jun 13 '11 at 20:20
1

Having played around with the chart control I haven't been able to find a simple solution to your problem. However the following may help:

Have you considered setting the maximum and minimum values for the axes yourself? If you round the actual maximum and minimum values to the nearest sensible "round" number (5, 10, 0.5, 0.01) this should make the calculated intervals a bit more friendly.

I understand this is not an ideal solution but by carefully choosing the maximum and/or minimum values you can ensure the intervals are "nicer" numbers. If the range of your axes is say divisible by 2, 5 & 10 it should result in fairly nice intervals.

Richard Smith
  • 539
  • 7
  • 14
  • I've attempted setting min and max myself, but these charts are used for analysis, and as soon as you zoom into a custom region, it loses the nice round numbers and goes back to this undesired behavior. In addition, setting the minimum to -10 sometimes results in -10.00000023 or similar. So, you're halfway there; it does fix the initial display, but with all the zooming that will happen, it's not a complete solution to the issue. Good to hear I'm not the only one, though! – drharris Dec 10 '10 at 00:07
1

Why not modify number format string.

Create format string

string formatString = "{0.00";

Identify zoom level, say zoomLevel = 2;

formatString = formatString.PadRight(5+zoomLevel, '0');
formatString += "}";

Now use this format on axis legend. Use string builder or some better way to modify the format string.

hungryMind
  • 6,931
  • 4
  • 29
  • 45
  • The problem is that "zoom level" has little meaning. The scale won't always be the same (sometimes, X axis may range 100-120, and other times from 0-4000). Plus, the user can self-select a zoom window, meaning that there is no explicit way to determine how many decimal places to format to. Good answer in theory, but it just doesn't match up with the object model here. – drharris Jan 24 '11 at 22:33
0

To provide the result with minimal cost you can use exponential scientific format

gabba
  • 2,815
  • 2
  • 27
  • 48
  • If this were an in-house application used only by science-minded people, that would be great! However, we have a user base that ranges from university professor to farmer. Teaching some of these people to read exponential format would be nearly impossible. Also, using scientific numbers does not prevent the problem of too many decimal places (as in 2.6666684583e-4) – drharris Dec 10 '10 at 00:09
  • Just use string.Format("{0:e2}", 123.456789). Also try to aply custom converter formater. – gabba Dec 10 '10 at 08:00
0

You can attach to customize event. From there, you can modify the labels on x-axis:

var xAxisLabels = chart1.ChartAreas[0].AxisX.CustomLabels;
...
xAxisLabels[0].Text = ...

set min. and max. values:

 chart1.ChartAreas[0].AxisX.Maximum = ...;

etc.

šljaker
  • 7,294
  • 14
  • 46
  • 80
0

you can dynamically update the max and min based on your data set. each time user zooms in, you do a FOREACH on every point and get the stats and based on that set your max and min

JOE SKEET
  • 7,950
  • 14
  • 48
  • 64
  • Code? How to detect when the user zooms? How to only retrieve points that are in the window while the zoom is active? – drharris Mar 23 '11 at 18:35
0

It helps to set the IntervalOffset of the axis, here an example:

Private Sub chMap_AxisViewChanged(sender As System.Object, e As System.Windows.Forms.DataVisualization.Charting.ViewEventArgs) Handles chMap.AxisViewChanged
  'the grid ticks are rounded values
  e.Axis.IntervalOffset = -e.Axis.ScaleView.ViewMinimum
End Sub
Austin Henley
  • 4,625
  • 13
  • 45
  • 80
David
  • 11
  • 1