Search code examples
vb.netwinformsmschart

Display x-axis label at certain data-points in mschart


I'm trying to plot a normal distribution curve (as a SeriesChartType.Spline) with a selected items location on that curve. My x-axis is a little messy so I'm trying to tidy it up but I can't figure a way to show the axis label at specific locations.

I'd like to show the value at {x(0), x(mean), x(n)} and also the x-axis value of the selected item's data-point on the curve.

enter image description here

I've tried playing with the

.ChartAreas(0).AxisX.Interval 

but I don't necessarily have a standard interval range.

Is there a way I can display the x-axis label only at specified data points?

[EDIT]:

As suggested I implemented several custom labels for this chart. They are not exactly what I'd call intuitive to use but they did the job in the end.

'//create x-axis labels
mu = Math.Round(mu, 2, MidpointRounding.AwayFromZero)
bci = Math.Round(CDbl(bci), 2, MidpointRounding.AwayFromZero)
Dim muLabel = String.Format("{0}({1})", "µ", mu)

'//Fit axis
With .ChartAreas(0)
    With .AxisX
        .MajorGrid.LineWidth = 0
        .MajorTickMark.Enabled = false
        .Minimum = 0
        With .CustomLabels
            .Add(New CustomLabel(0, 0.4, 0, 0, LabelMarkStyle.LineSideMark))                        '//origin label
            .Add(New CustomLabel(mu-10, mu + 10, muLabel, 0, LabelMarkStyle.LineSideMark))          '//mean label)
            .Add(New CustomLabel(bci-10, bci + 10, bci.ToString, 0, LabelMarkStyle.LineSideMark))   '//index label
        End With
        With .LabelStyle
            .Format = "{0.00}"
            .Font = New Font("Microsoft Sans Serif", 8)
        End With
...

The ranges I picked for the labels are a bit arbitrary. My data distribution is not going to change much immediately so I picked a range that looked reasonable with the font so the labels sit in the centre. Looks much more readable now: https://i.sstatic.net/VV4yd.png


Solution

  • You have a choice of either

    • Replacing the normal labels by CustomLabels. They are a bit tricky since you can't set their position. Instead you need two positions (FromPosition and ToPosition) to declare the range where the CustomLabel shall be centered. Note that once you use CustomLabels no normal ones will show.

    • Or you can add TextAnnotations. You can set AnchorX to the value you want and the Y position to the minimum of your y-values. Getting these right is also a little tricky, involving the axes of the Annotation and also the IsSizeAlwaysRelative which should be false.

    • Or you could code the Pre- or PostPaint events and Graphics.DrawString or TextRenderer.DrawText the text you want using the ValueToPixelPosition axes functions to get the coordinates. This may actually be the easiest to do..