Selecting multiple sections on a chart in c#

2020-04-21 03:16发布

I am trying to make a simple WindowsFormAplication with data displayed in charts with type column.

Now, the idea is for the user to select a part of the chart, and for the program to find the same numbers from the same dataset and select all of them on the SAME chart. My program does just that, up to the point where it needs to display multiple selections on that chart.

I only found one way of selecting data, and that is via Cursor.SetSelectionPosition(double, double); but there doesn't seem to be an option for multiple selection.

Is this even possible on a standard chart? Any suggestions on how to accomplish this in C# will be much appreciated.

标签: c# charts
1条回答
forever°为你锁心
2楼-- · 2020-04-21 03:41

There can only be one range selected at any time.

So you need to ..

  • ..collect the ranges and
  • ..probably also collect the selected DataPoints.
  • Finally you also need to decide on a UI to clear the selections.

An simple way to display several selections, very similar to the cursor selection is adding Striplines..:

enter image description here

Here is the code for the above result; note that it assumes that your values will fit in a float and abuses the SizeF structure to store the start and end values of the selections. If you want to be more precise you can replace it with a Tuple<double, double>..:

First three class level variables to hold the data, the ongoing selection, the list of ranges and a list of DataPoint indices:

SizeF curRange = SizeF.Empty;
List<SizeF> ranges = new List<SizeF>();
List<int> selectedIndices = new List<int>();

This event holds the new selections in the param e, so we can store them:

private void chart1_SelectionRangeChanging(object sender, CursorEventArgs e)
{
    curRange = new SizeF((float)e.NewSelectionStart, (float)e.NewSelectionEnd);
}

Now the selection process is done; the selection data is lost by now, but we have stored them. So we can add the new range, collect the newly selected DataPoint indices and finally create and display a new StripLine:

private void chart1_SelectionRangeChanged(object sender, CursorEventArgs e)
{
    ranges.Add(curRange);
    selectedIndices.Union(collectDataPoints(chart1.Series[0], 
                          curRange.Width, curRange.Height))
                   .Distinct();

    StripLine sl = new StripLine();
    sl.BackColor = Color.FromArgb(255, Color.LightSeaGreen);
    sl.IntervalOffset = Math.Min(curRange.Width, curRange.Height);
    sl.StripWidth = Math.Abs(curRange.Height - curRange.Width);
    chart1.ChartAreas[0].AxisX.StripLines.Add(sl);
}

This little routine should collect all DataPoint indices in a range:

List<int> collectDataPoints(Series s, double min, double max)
{
    List<int> hits = new List<int>();
    for (int i = 0; i < s.Points.Count ; i++)
        if (s.Points[i].XValue >= min && s.Points[i].XValue <= max) hits.Add(i);
    return hits;
}

To clear the selection you clear the two lists, the StripLines collection, and the curRange structure.

查看更多
登录 后发表回答