6
votes

I'm using the C# built-in Winforms Chart control (System.Windows.Forms.DataVisualization.Charting.Chart) with its built-in ability to let the user select a range. What I'd like to do is to read back what range the user has selected. Surely there must be some easy way to do this, but I haven't been able to find it.

The cursor is enabled like so:

var ca = chart1.ChartAreas["ChartArea1"].CursorX;
ca.CursorX.IsUserEnabled = true;
ca.CursorX.IsUserSelectionEnabled = true;

I am aware that I can make the chart zoom when the user selects a range by enabling ca.AxisX.ScaleView.Zoomable, but I don't want the picture to change: instead I am using the chart as a way to display information and let the user select a range of X values for which I then do some extra processing.

I tried hooking to chart1.SelectionRangeChanged and that indeed fires every time the range is changed - I just can't seem to get the selection range from the CursorEventArg I get back. It has "NewSelectionStart" and "NewSelectionEnd" fields, but those are NaN, disappointingly. I tried looking at the various properties of the chart and the axes, but didn't find anything that sounded promising.

Further investigation reveals the ChartArea.CursorX.SelectionStart property which sounds like exactly what I need... except that it's NaN too. I don't know whether this is normal or I'm hitting some sort of bug?

So, how can I figure out what range the user selected?

2
Alternatively, I'll take suggestions of free chart controls that let the user select a range. But I'd much rather be able to use what I already have.redtuna

2 Answers

7
votes

OK, well, I figured it out. Here's the scoop:

There's a SelectionRangeChang*ing* event, and when that one runs the ChartArea.CursorX.SelectionStart and ChartArea.CursorX.SelectionEnd fields have correct values in them. But the user hasn't released the mouse button yet, so you should just store them.

When the user releases the mouse button, the SelectionRangeChang*ed* event fires. Somehow it's designed in such a way that SelectionStart and SelectionEnd are reset to NaN (just like the NewSelectionStart and NewSelectionEnd fields in the event parameters). What you have to do is to use the values that you squirreled away from the other event handler now that you know the time is right to use them.

So there you have it! Hopefully this answer will save someone else from wasting time.

0
votes

In addition to redtuna to set cursors in a c# chart:

It worked for me to use "SelectionRangeChanging" instead of "SelectionRangeChanged" to not get the NaN issue:

When initializing the Form

this.chart1.SelectionRangeChanging += chart1_SelectionRangeChanging;

and

        chart1.ChartAreas[0].CursorX.IsUserEnabled = false;         // red cursor at SelectionEnd
        chart1.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
        chart1.ChartAreas[0].AxisX.ScaleView.Zoomable = false;      // zoom into SelectedRange
        chart1.ChartAreas[0].AxisX.ScrollBar.IsPositionedInside = true;
        chart1.ChartAreas[0].CursorX.Interval = 0.01;               // set "resolution" of CursorX

What is executed if the range is chosen / the cursors are set

private void chart1_SelectionRangeChanging(object sender, CursorEventArgs e)
    {
        double x1 = x1 = e.NewSelectionStart; // or: chart1.ChartAreas[0].CursorX.SelectionStart;
        double x2 = e.NewSelectionEnd;        // or: x2 = chart1.ChartAreas[0].CursorX.SelectionEnd;

        double diffx1x2 = x2 - x1;
    }    

To zoom in & out (x-axis) I just added a button that takes the cursor values. That way zooming by mouseClick (ScaleView.Zoomable = false;) does not interfere my cursor positioning :)

 private void button_ZoomIn(object sender, EventArgs e)
    {
        double x1 = chart1.ChartAreas[0].CursorX.SelectionStart;  // x1 = X1
        double x2 = chart1.ChartAreas[0].CursorX.SelectionEnd;    // x2 = X2

        if (x2 > x1)
        {
            // hard setting: chart1.ChartAreas[0].AxisX.Minimum = x1;
            // hard setting: chart1.ChartAreas[0].AxisX.Maximum = x2;
            chart1.ChartAreas[0].AxisX.ScaleView.Zoom(x1,x2); // dynamic approach with scrollbar
        }
        else
        {
            chart1.ChartAreas[0].AxisX.ScaleView.Zoom(x2,x1);
        }
    }

Zoom out

private void button_ZoomOut(object sender, EventArgs e)
    {
        chart1.ChartAreas[0].AxisX.ScaleView.ZoomReset(0);
    }

Zooming can also be implemented by mouseWheel: how to enable zooming in Microsoft chart control by using Mouse wheel And if you also want right-click action in the chart: How to get a right click mouse event? Changing EventArgs to MouseEventArgs causes an error in Form1Designer?