15
votes

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).

7
AFAIK, the Charting controls are based on Dundas controls. Microsoft acquired Dundas’s data visualization components some time ago. More info here - CGK
There are no pictures in your edit? - noelicus
@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

7 Answers

6
votes

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;
1
votes

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.

1
votes

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.

0
votes

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

0
votes

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.

0
votes

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

0
votes

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