In the constructor I am basically generating a bunch of random values to use in the chart. As you can see, I am actually using two series. The reason for this is that the I wanted something that would be easy for the user to click on. A point chart provides a more visible, clickable point when overlaid on top of the line chart that actually displays the data.
#region Fields // Series item currently being dragged ChartSeriesItem dragSeriesItem = null; // Current mouse position Point mPos = new Point(); // Delta of mouse movement while dragging Point mDelta = new Point(); #endregion #region Constructor(s) public Form1() { InitializeComponent(); // Generate a random series // Uses a point series and a line series together, (points can be clicked, lines cannot) Random rnd = new Random(); for (int i = 0; i < 10; i++) { int val = rnd.Next() % 10; radChart1.Series[0].AddItem(val); radChart1.Series[1].AddItem(val); } // don't show the labels of the line series radChart1.Series[0].Appearance.LabelAppearance.Visible = false; } #endregionHere, I am detecting when and what series item the user is clicking on. If an item was clicked, I store it as the current item being dragged in the dragSeriesItem variable.
private void radChart1_MouseDown(object sender, MouseEventArgs e) { foreach (ChartSeriesItem seriesItem in radChart1.Series[1].Items) { if (seriesItem.ActiveRegion.CheckPoint(e.Location)) { this.dragSeriesItem = seriesItem; radChart1.Refresh(); mPos = Cursor.Position; mDelta = new Point(0, 0); } } }
In this event, if the user is currently dragging a node, I detect if there has been a change in the mouse cursor position. If so, I increment the YValue of the series item based on that change. I also update the mouse position to match the position of where the node was dragged.
private void radChart1_MouseMove(object sender, MouseEventArgs e) { if (dragSeriesItem != null) { // get the delta of the mouse cursor mDelta.X = Cursor.Position.X - mPos.X; mDelta.Y = Cursor.Position.Y - mPos.Y; // update the seriesItem position based on the - or + delta of the mouse if (mDelta.Y < 0) dragSeriesItem.YValue++; else if (mDelta.Y > 0) dragSeriesItem.YValue--; radChart1.Series[0].Items[dragSeriesItem.Index].YValue = dragSeriesItem.YValue; // Get center of point, update the mouse position RectangleF regionBounds = dragSeriesItem.ActiveRegion.Region.GetBounds(); Point position = new Point((int)(regionBounds.Left + regionBounds.Width / 2), (int)(regionBounds.Top + regionBounds.Height / 2)); Cursor.Position = radChart1.PointToScreen(position); // save the new mouse position mPos = Cursor.Position; // redraw the chart radChart1.Refresh(); } }
In this event, I simply set the dragSeriesItem variable to null to represent that no item is currently being dragged.
private void radChart1_MouseUp(object sender, MouseEventArgs e) { dragSeriesItem = null; }
Currently, when you drag a node, the mouse cursor feels a bit jumpy. You could probably add a lot of extra precision to this approach if you decrease the amount of the point step value from an integer to a floating point value. (i.e. dragSeriesItem.YValue += .5)
I am not exactly sure what the business use case for something like this would be, but, if you've found a need for something like this, I would love to hear about it. Please comment below.