Answered by:
DataPoint Drawing, Position and Interactivity
Question

Hi, Just out of curiosity, I wonder if it is possible to 'grab' a datapoint on mouse down and drag it around the screen, and on mouse up the point is dropped to the nearest xValue based on its position. I have read that it should be possible by tapping into the chart paint events?
anyone know if it is possible? or is this too complex for mschart?
Thursday, June 17, 2010 12:31 PM
Answers

Hello again, I modified your code to work like I presume you want it to. Basically I just modified the way the total is calculated.
Imports System.Windows.Forms.DataVisualization.Charting Public Class ExampleForm3 Private _selectedPoint As DataPoint Private _selectedPointIndex As Integer Private _selectedSeries As Series Private Sub ExampleForm_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Chart1.Series.Clear() 'Add a series to the chart Dim series As New Series("SERIES") series.ChartType = SeriesChartType.StackedColumn Chart1.Series.Add(series) 'Add a series to the chart Dim series2 As New Series("SERIES2") series2.ChartType = SeriesChartType.StackedColumn Chart1.Series.Add(series2) 'Add a series to the chart Dim series3 As New Series("SERIES3") series3.ChartType = SeriesChartType.StackedColumn Chart1.Series.Add(series3) 'Add data to series Dim xValues As Integer() = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} Dim yValues As Integer() = {2, 4, 6, 1, 5, 4, 8, 9, 4, 3} series.Points.DataBindXY(xValues, yValues) series2.Points.DataBindXY(xValues, yValues) series3.Points.DataBindXY(xValues, yValues) End Sub Private Sub Chart1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseDown Dim result As HitTestResult = Chart1.HitTest(e.X, e.Y) If result.ChartElementType = ChartElementType.DataPoint Then _selectedPointIndex = result.PointIndex _selectedSeries = result.Series _selectedPoint = result.Series.Points(_selectedPointIndex) End If End Sub Private Sub Chart1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseMove ' Check if data point selected If Not _selectedPoint Is Nothing Then Dim total As Double = 0 'Calculate the total up to (not including) the selected point. For Each s As Series In Chart1.Series 'Exit loop when reached the selected series If s.Equals(_selectedSeries) Then Exit For total = total + s.Points(_selectedPointIndex).YValues(0) Next 'Mouse coordinates should not be outside of the chart Dim yValue As Double = Chart1.ChartAreas("ChartArea1").AxisY.PixelPositionToValue(Math.Max(Math.Min(e.Y, Chart1.Size.Height  1), 0)) ' Minus the total value found for correction. yValue = yValue  total yValue = Math.Min(yValue, Chart1.ChartAreas("ChartArea1").AxisY.Maximum) yValue = Math.Max(yValue, Chart1.ChartAreas("ChartArea1").AxisY.Minimum) ' Update selected point Y value _selectedPoint.YValues(0) = yValue ' Invalidate chart Chart1.Invalidate() Else ' Set different shape of cursor over the data points Dim hitResult As HitTestResult = Chart1.HitTest(e.X, e.Y) If hitResult.ChartElementType = ChartElementType.DataPoint Then Chart1.Cursor = Cursors.Hand Else Chart1.Cursor = Cursors.Default End If End If End Sub Private Sub Chart1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseUp _selectedPoint = Nothing End Sub End Class
 Marked as answer by enexooone Tuesday, June 29, 2010 7:47 AM
Monday, June 28, 2010 2:57 PMModerator 
Instead of moving the data point with the xvalue, you should change the yvalue of the corresponding point in the same series.
This example (as well as the previous ones) will probably only work if there are the same amount of points in each series and the xvalues correspond to the points' xindexes (1, 2, 3, 4, 5 ... )
Also, note that if you disable the labels, you won't be able to modify the bottom most series' points if the yvalue goes to zero, since it will be under the xaxis.
Imports System.Windows.Forms.DataVisualization.Charting Public Class Form1 'The point that is dragged Private _selectedPoint As DataPoint Private _selectedPointIndex As Integer Private _selectedSeries As Series Private _selectedValue As Double 'The point the selected point is being dragged over Private _currentPoint As DataPoint Private _currentValue As Double 'The previous point the selected point was dragged over '(To restore the value after moving over) Private _previousPoint As DataPoint Private _previousValue As Double Private Sub ExampleForm_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Chart1.Series.Clear() 'Add a series to the chart Dim series As New Series("SERIES") series.ChartType = SeriesChartType.StackedColumn Chart1.Series.Add(series) 'Add a series to the chart Dim series2 As New Series("SERIES2") series2.ChartType = SeriesChartType.StackedColumn Chart1.Series.Add(series2) 'Add a series to the chart Dim series3 As New Series("SERIES3") series3.ChartType = SeriesChartType.StackedColumn Chart1.Series.Add(series3) 'Add data to series Dim xValues As Integer() = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} Dim yValues As Integer() = {2, 4, 6, 1, 5, 4, 8, 9, 4, 3} series.Points.DataBindXY(xValues, yValues) series2.Points.DataBindXY(xValues, yValues) series3.Points.DataBindXY(xValues, yValues) For Each s In Chart1.Series s.IsValueShownAsLabel = True Next End Sub Private Sub Chart1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseDown Dim result As HitTestResult = Chart1.HitTest(e.X, e.Y) 'If the bottom data point value is 0, you can only drag from the label. If result.ChartElementType = ChartElementType.DataPoint Or result.ChartElementType = ChartElementType.DataPointLabel Then _selectedPointIndex = result.PointIndex _selectedSeries = result.Series _selectedPoint = result.Series.Points(_selectedPointIndex) _selectedValue = _selectedPoint.YValues(0) End If End Sub Private Sub Chart1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseMove ' Check if data point selected If Not _selectedPoint Is Nothing Then Dim area As ChartArea = Chart1.ChartAreas(0) If e.Button = Windows.Forms.MouseButtons.Left Then Dim total As Double = 0 'Calculate the total up to (not including) the selected point. For Each s As Series In Chart1.Series 'Exit loop when reached the selected series If s.Equals(_selectedSeries) Then Exit For total = total + s.Points(_selectedPointIndex).YValues(0) Next 'Mouse coordinates should not be outside of the chart Dim yValue As Double = area.AxisY.PixelPositionToValue(Math.Max(Math.Min(e.Y, Chart1.Size.Height  1), 0)) ' Minus the total value found for correction. yValue = yValue  total yValue = Math.Min(yValue, area.AxisY.Maximum) yValue = Math.Max(yValue, area.AxisY.Minimum) ' Update selected point Y value _selectedPoint.YValues(0) = Math.Round(yValue) 'Round the double value 'Invalidate chart Chart1.Invalidate() ElseIf e.Button = Windows.Forms.MouseButtons.Right Then 'Find the closest point index based on the xvalue Dim xValue As Double = Math.Round(area.AxisX.PixelPositionToValue(Math.Max(Math.Min(e.X, Chart1.Size.Width  1), 0))) xValue = Math.Max(Math.Min(xValue, _selectedSeries.Points.Count), 1) _currentPoint = _selectedSeries.Points(CInt(xValue  1)) _currentValue = _currentPoint.YValues(0) If _previousPoint Is Nothing Then _previousPoint = _currentPoint _previousValue = _previousPoint.YValues(0) End If If Not _currentPoint.Equals(_previousPoint) Then _previousPoint.YValues(0) = _previousValue  _selectedValue _currentPoint.YValues(0) = _currentValue + _selectedValue _previousPoint = _currentPoint _previousValue = _previousPoint.YValues(0) End If 'Invalidate chart Chart1.Invalidate() End If Else ' Set different shape of cursor over the data points Dim result As HitTestResult = Chart1.HitTest(e.X, e.Y) If result.ChartElementType = ChartElementType.DataPoint Or result.ChartElementType = ChartElementType.DataPointLabel Then Chart1.Cursor = Cursors.Hand Else Chart1.Cursor = Cursors.Default End If End If End Sub Private Sub Chart1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseUp _previousPoint = Nothing _selectedPoint = Nothing End Sub End Class
 Marked as answer by enexooone Tuesday, June 29, 2010 1:45 PM
Tuesday, June 29, 2010 1:00 PMModerator 
I mentioned this in one of my earlier posts. Try setting Series.IsXValueIndexed = True for each series in the chart. If you have missing data points, call the Chart.DataManipulator.InsertEmptyPoints method to align the series.
'Add data to series Dim xValues As DateTime() = {#1/1/2011#, #1/2/2011#, #1/3/2011#, #1/4/2011#, #1/5/2011#, #1/6/2011#, #1/7/2011#, #1/8/2011#, #1/9/2011#, #1/10/2011#} Dim yValues As Integer() = {2, 4, 6, 1, 5, 4, 8, 9, 4, 3} series.Points.DataBindXY(xValues, yValues) series2.Points.DataBindXY(xValues, yValues) series3.Points.DataBindXY(xValues, yValues) series.IsXValueIndexed = True series2.IsXValueIndexed = True series3.IsXValueIndexed = True 'Change the interval to whatever your data has. Chart1.ChartAreas(0).AxisX.Interval = 1 Chart1.ChartAreas(0).AxisX.IntervalType = DateTimeIntervalType.Days 'Not necessary unless you have missing data points in some of the series. Chart1.DataManipulator.InsertEmptyPoints(1, IntervalType.Days, "SERIES,SERIES2,SERIES3")
 Marked as answer by enexooone Thursday, January 20, 2011 9:49 AM
Wednesday, January 19, 2011 1:46 PMModerator
All replies

In the Forms Charting it is fairly easy to do. There is a example of it in the Forms Samples Environment (at least in the .Net 3.5 samples). Content Tab > Chart Features > Interactive Charting > Selection > Changing values by dragging.
Here is a piece of code to demonstrate. Mostly the same as the samples:
Imports System.Windows.Forms.DataVisualization.Charting Public Class ExampleForm Private _mouseDown As Boolean = False Private _draggedPoint As DataPoint Private Sub ExampleForm_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Chart1.Series.Clear() 'Set axisX limits and interval so that they wont change when moving data points Chart1.ChartAreas(0).AxisX.Minimum = 0 Chart1.ChartAreas(0).AxisX.Maximum = 10 Chart1.ChartAreas(0).AxisX.Interval = 1 'Add a series to the chart Dim series As New Series("SERIES") series.ChartType = SeriesChartType.Point 'Will work with other types too. series.MarkerSize = 10 Chart1.Series.Add(series) 'Add data to series Dim xValues As Integer() = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} Dim yValues As Integer() = {2, 4, 6, 1, 5, 4, 8, 9, 4, 3} series.Points.DataBindXY(xValues, yValues) End Sub Private Sub Chart1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseDown Dim result As HitTestResult = Chart1.HitTest(e.X, e.Y) If result.ChartElementType = ChartElementType.DataPoint Then _draggedPoint = Chart1.Series(0).Points(result.PointIndex) _mouseDown = True End If End Sub Private Sub Chart1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseMove If _mouseDown Then Dim area As ChartArea = Chart1.ChartAreas(0) 'Mouse coordinates should not be outside of the chart Dim yValue As Double = area.AxisY.PixelPositionToValue(Math.Max(Math.Min(e.Y, Chart1.Size.Height  1), 0)) yValue = Math.Min(yValue, area.AxisY.Maximum) yValue = Math.Max(yValue, area.AxisY.Minimum) Dim xValue As Double = area.AxisX.PixelPositionToValue(Math.Max(Math.Min(e.X, Chart1.Size.Width  1), 0)) xValue = Math.Min(xValue, area.AxisX.Maximum) xValue = Math.Max(xValue, area.AxisX.Minimum) _draggedPoint.XValue = xValue _draggedPoint.YValues(0) = yValue Chart1.Invalidate() Else 'Set different shape of cursor over the data points Dim result As HitTestResult = Chart1.HitTest(e.X, e.Y) If result.ChartElementType = ChartElementType.DataPoint Then Chart1.Cursor = Cursors.Hand Else Chart1.Cursor = Cursors.Default End If End If End Sub Private Sub Chart1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseUp _mouseDown = False End Sub End Class
On the Web side I suspect this could be possible, but would be more complicated and involve javascript and ajax.
Friday, June 18, 2010 10:18 AMModerator 
Hi Sipla, thanks for replying. try setting the series type to column and see what happens!, Ideally I was thinking when the mouse is released the point that is selected gets dropped to the nearest xvalue based on the pixel location. something like the Annotation Position changing event (in the samples) where it 'locks on' to the nearest point.
thanks anyway
regards,
enex
Friday, June 18, 2010 12:48 PM 
It's very simple to get the data points to lock on to round values for example. Just set
_draggedPoint.XValue = Math.Round(xValue) _draggedPoint.YValues(0) = Math.Round(yValue)
in the Chart1.MouseMove event.
You'll have to do some more coding if you want to get the points to lock on to any axis interval though.
This will also "cure" the funky column width changes that you get in the original example, if you change the chart type to column. :)
Friday, June 18, 2010 5:25 PMModerator 
Hi Sipla that does work really well but how do i work with multiple series? I plan on using the code for a stacked column chart with muliple series. I have looked over the mouse_down event and I can see it does refer to the series with an index of zero.
Also you would probably know the answer to the other problem im having, basically I have adapted the code found in the samples to move the charts datapoints up and down to adjust the yValues. however because I am using a stacked column chart and I move a datapoint that is stacked on another, the point will jump up out of position. I think this is due to the method PixelPositionToValue. would you know how to correct this issue?
im basically trying to loop through if the points are the selected stacks xvalue add them up and then I need to minus them to gain the correct position?? heres what i have tried:
Private Sub Chart1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseMove ' Check if data point selected If Not (selectedDataPoint Is Nothing) Then ' Mouse coordinates should not be outside of the chart Dim coordinate As Integer = e.Y If coordinate < 0 Then coordinate = 0 End If If coordinate > Chart1.Size.Height  1 Then coordinate = Chart1.Size.Height  1 End If Dim total As Integer 'Loop for each series For Each s In Chart1.Series 'Go through the datapoints For Each p As DataPoint In s.Points 'if the Datapoint found has the correct xValue If p.XValue = selectedDataPoint.XValue Then 'Add to total total = total + p.YValues(0) 'Minus ANY previous series YValue here End If Next Next For Each s In Chart1.Series For Each p As DataPoint In s.Points If p.XValue = selectedDataPoint.XValue Then End If Next Next 'This line is incorrect??? total = total  selectedDataPoint.YValues(0) 'Minus the total value found for correction. Dim yValue As Integer = Chart1.ChartAreas("ChartArea1").AxisY.PixelPositionToValue(coordinate)  total yValue = Math.Min(yValue, Chart1.ChartAreas("ChartArea1").AxisY.Maximum) yValue = Math.Max(yValue, Chart1.ChartAreas("ChartArea1").AxisY.Minimum) ' Update selected point Y value selectedDataPoint.YValues(0) = yValue ' Invalidate chart Chart1.Invalidate() Else ' Set different shape of cursor over the data points Dim hitResult As HitTestResult = Chart1.HitTest(e.X, e.Y) If hitResult.ChartElementType = ChartElementType.DataPoint Then Chart1.Cursor = Cursors.Hand Else Chart1.Cursor = Cursors.Default End If End If End Sub 'Chart1_MouseMove
thanks in advance, the code you provided is very helpful
Regards,
enex
Monday, June 21, 2010 1:26 PM 
Hello again, I modified your code to work like I presume you want it to. Basically I just modified the way the total is calculated.
Imports System.Windows.Forms.DataVisualization.Charting Public Class ExampleForm3 Private _selectedPoint As DataPoint Private _selectedPointIndex As Integer Private _selectedSeries As Series Private Sub ExampleForm_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Chart1.Series.Clear() 'Add a series to the chart Dim series As New Series("SERIES") series.ChartType = SeriesChartType.StackedColumn Chart1.Series.Add(series) 'Add a series to the chart Dim series2 As New Series("SERIES2") series2.ChartType = SeriesChartType.StackedColumn Chart1.Series.Add(series2) 'Add a series to the chart Dim series3 As New Series("SERIES3") series3.ChartType = SeriesChartType.StackedColumn Chart1.Series.Add(series3) 'Add data to series Dim xValues As Integer() = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} Dim yValues As Integer() = {2, 4, 6, 1, 5, 4, 8, 9, 4, 3} series.Points.DataBindXY(xValues, yValues) series2.Points.DataBindXY(xValues, yValues) series3.Points.DataBindXY(xValues, yValues) End Sub Private Sub Chart1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseDown Dim result As HitTestResult = Chart1.HitTest(e.X, e.Y) If result.ChartElementType = ChartElementType.DataPoint Then _selectedPointIndex = result.PointIndex _selectedSeries = result.Series _selectedPoint = result.Series.Points(_selectedPointIndex) End If End Sub Private Sub Chart1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseMove ' Check if data point selected If Not _selectedPoint Is Nothing Then Dim total As Double = 0 'Calculate the total up to (not including) the selected point. For Each s As Series In Chart1.Series 'Exit loop when reached the selected series If s.Equals(_selectedSeries) Then Exit For total = total + s.Points(_selectedPointIndex).YValues(0) Next 'Mouse coordinates should not be outside of the chart Dim yValue As Double = Chart1.ChartAreas("ChartArea1").AxisY.PixelPositionToValue(Math.Max(Math.Min(e.Y, Chart1.Size.Height  1), 0)) ' Minus the total value found for correction. yValue = yValue  total yValue = Math.Min(yValue, Chart1.ChartAreas("ChartArea1").AxisY.Maximum) yValue = Math.Max(yValue, Chart1.ChartAreas("ChartArea1").AxisY.Minimum) ' Update selected point Y value _selectedPoint.YValues(0) = yValue ' Invalidate chart Chart1.Invalidate() Else ' Set different shape of cursor over the data points Dim hitResult As HitTestResult = Chart1.HitTest(e.X, e.Y) If hitResult.ChartElementType = ChartElementType.DataPoint Then Chart1.Cursor = Cursors.Hand Else Chart1.Cursor = Cursors.Default End If End If End Sub Private Sub Chart1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseUp _selectedPoint = Nothing End Sub End Class
 Marked as answer by enexooone Tuesday, June 29, 2010 7:47 AM
Monday, June 28, 2010 2:57 PMModerator 
Hi Sipla that code is highly helpful (ive been trying to solve that for weeks thanks alot!)
I am able to drag the datapoints up and down how I want. You wrote some code that moves the datapoints and drops them where the user specifies, this does work well for the point style series. I would like to apply the idea to my stacked column chart. Heres what I'd like to do:
instead of adjusting the Yvalue for the datapoint I would like to move it from side to side so I can drop it in another stack and the Yvalue will update accordingly depending on the stack selected all it will do is add the selectedpoint Yvalue to which ever series in the target stack matches the selected points series
I can tear out a datapoint and move it side to side with the code you provided, but I would like to update the stack with the new yvalue heres the code I have so far again any help is highly helpful!
edit: I was testing with the top series "series(2)" but I would like to apply this to any series selected.
Imports System.Windows.Forms.DataVisualization.Charting Public Class Form1 Private _selectedPoint As DataPoint Private _selectedPointIndex As Integer Private _selectedSeries As Series Private _mouseDown As Boolean = False Private _draggedPoint As DataPoint Private Sub ExampleForm_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load For Each s In Chart1.Series s.IsValueShownAsLabel = True Next End Sub Private Sub Chart1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseDown Dim result As HitTestResult = Chart1.HitTest(e.X, e.Y) If result.ChartElementType = ChartElementType.DataPoint Then _selectedPointIndex = result.PointIndex _selectedSeries = result.Series _selectedPoint = result.Series.Points(_selectedPointIndex) _draggedPoint = Chart1.Series(2).Points(result.PointIndex) _mouseDown = True End If End Sub Private Sub Chart1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseMove If e.Button = Windows.Forms.MouseButtons.Left Then ' Check if data point selected If Not _selectedPoint Is Nothing Then Dim total As Integer = 0 'Calculate the total up to (not including) the selected point. For Each s As Series In Chart1.Series 'Exit loop when reached the selected series If s.Equals(_selectedSeries) Then Exit For total = total + s.Points(_selectedPointIndex).YValues(0) Next 'Mouse coordinates should not be outside of the chart Dim yValue As Integer = Chart1.ChartAreas("ChartArea1").AxisY.PixelPositionToValue(Math.Max(Math.Min(e.Y, Chart1.Size.Height  1), 0)) ' Minus the total value found for correction. yValue = yValue  total yValue = Math.Min(yValue, Chart1.ChartAreas("ChartArea1").AxisY.Maximum) yValue = Math.Max(yValue, Chart1.ChartAreas("ChartArea1").AxisY.Minimum) ' Update selected point Y value _selectedPoint.YValues(0) = yValue ' Invalidate chart Chart1.Invalidate() Else ' Set different shape of cursor over the data points Dim hitResult As HitTestResult = Chart1.HitTest(e.X, e.Y) If hitResult.ChartElementType = ChartElementType.DataPoint Then Chart1.Cursor = Cursors.Hand Else Chart1.Cursor = Cursors.Default End If End If End If If e.Button = Windows.Forms.MouseButtons.Right Then If _mouseDown Then Dim area As ChartArea = Chart1.ChartAreas(0) Dim xValue As Double = area.AxisX.PixelPositionToValue(Math.Max(Math.Min(e.X, Chart1.Size.Width  1), 0)) xValue = Math.Min(xValue, area.AxisX.Maximum) xValue = Math.Max(xValue, area.AxisX.Minimum) _draggedPoint.XValue = Math.Round(xValue) Chart1.Invalidate() Else 'Set different shape of cursor over the data points Dim result As HitTestResult = Chart1.HitTest(e.X, e.Y) If result.ChartElementType = ChartElementType.DataPoint Then Chart1.Cursor = Cursors.Hand Else Chart1.Cursor = Cursors.Default End If End If End If End Sub Private Sub Chart1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseUp _selectedPoint = Nothing _mouseDown = False End Sub End Class
Tuesday, June 29, 2010 10:42 AM 
Instead of moving the data point with the xvalue, you should change the yvalue of the corresponding point in the same series.
This example (as well as the previous ones) will probably only work if there are the same amount of points in each series and the xvalues correspond to the points' xindexes (1, 2, 3, 4, 5 ... )
Also, note that if you disable the labels, you won't be able to modify the bottom most series' points if the yvalue goes to zero, since it will be under the xaxis.
Imports System.Windows.Forms.DataVisualization.Charting Public Class Form1 'The point that is dragged Private _selectedPoint As DataPoint Private _selectedPointIndex As Integer Private _selectedSeries As Series Private _selectedValue As Double 'The point the selected point is being dragged over Private _currentPoint As DataPoint Private _currentValue As Double 'The previous point the selected point was dragged over '(To restore the value after moving over) Private _previousPoint As DataPoint Private _previousValue As Double Private Sub ExampleForm_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Chart1.Series.Clear() 'Add a series to the chart Dim series As New Series("SERIES") series.ChartType = SeriesChartType.StackedColumn Chart1.Series.Add(series) 'Add a series to the chart Dim series2 As New Series("SERIES2") series2.ChartType = SeriesChartType.StackedColumn Chart1.Series.Add(series2) 'Add a series to the chart Dim series3 As New Series("SERIES3") series3.ChartType = SeriesChartType.StackedColumn Chart1.Series.Add(series3) 'Add data to series Dim xValues As Integer() = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} Dim yValues As Integer() = {2, 4, 6, 1, 5, 4, 8, 9, 4, 3} series.Points.DataBindXY(xValues, yValues) series2.Points.DataBindXY(xValues, yValues) series3.Points.DataBindXY(xValues, yValues) For Each s In Chart1.Series s.IsValueShownAsLabel = True Next End Sub Private Sub Chart1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseDown Dim result As HitTestResult = Chart1.HitTest(e.X, e.Y) 'If the bottom data point value is 0, you can only drag from the label. If result.ChartElementType = ChartElementType.DataPoint Or result.ChartElementType = ChartElementType.DataPointLabel Then _selectedPointIndex = result.PointIndex _selectedSeries = result.Series _selectedPoint = result.Series.Points(_selectedPointIndex) _selectedValue = _selectedPoint.YValues(0) End If End Sub Private Sub Chart1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseMove ' Check if data point selected If Not _selectedPoint Is Nothing Then Dim area As ChartArea = Chart1.ChartAreas(0) If e.Button = Windows.Forms.MouseButtons.Left Then Dim total As Double = 0 'Calculate the total up to (not including) the selected point. For Each s As Series In Chart1.Series 'Exit loop when reached the selected series If s.Equals(_selectedSeries) Then Exit For total = total + s.Points(_selectedPointIndex).YValues(0) Next 'Mouse coordinates should not be outside of the chart Dim yValue As Double = area.AxisY.PixelPositionToValue(Math.Max(Math.Min(e.Y, Chart1.Size.Height  1), 0)) ' Minus the total value found for correction. yValue = yValue  total yValue = Math.Min(yValue, area.AxisY.Maximum) yValue = Math.Max(yValue, area.AxisY.Minimum) ' Update selected point Y value _selectedPoint.YValues(0) = Math.Round(yValue) 'Round the double value 'Invalidate chart Chart1.Invalidate() ElseIf e.Button = Windows.Forms.MouseButtons.Right Then 'Find the closest point index based on the xvalue Dim xValue As Double = Math.Round(area.AxisX.PixelPositionToValue(Math.Max(Math.Min(e.X, Chart1.Size.Width  1), 0))) xValue = Math.Max(Math.Min(xValue, _selectedSeries.Points.Count), 1) _currentPoint = _selectedSeries.Points(CInt(xValue  1)) _currentValue = _currentPoint.YValues(0) If _previousPoint Is Nothing Then _previousPoint = _currentPoint _previousValue = _previousPoint.YValues(0) End If If Not _currentPoint.Equals(_previousPoint) Then _previousPoint.YValues(0) = _previousValue  _selectedValue _currentPoint.YValues(0) = _currentValue + _selectedValue _previousPoint = _currentPoint _previousValue = _previousPoint.YValues(0) End If 'Invalidate chart Chart1.Invalidate() End If Else ' Set different shape of cursor over the data points Dim result As HitTestResult = Chart1.HitTest(e.X, e.Y) If result.ChartElementType = ChartElementType.DataPoint Or result.ChartElementType = ChartElementType.DataPointLabel Then Chart1.Cursor = Cursors.Hand Else Chart1.Cursor = Cursors.Default End If End If End Sub Private Sub Chart1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Chart1.MouseUp _previousPoint = Nothing _selectedPoint = Nothing End Sub End Class
 Marked as answer by enexooone Tuesday, June 29, 2010 1:45 PM
Tuesday, June 29, 2010 1:00 PMModerator 
Hi Sipla, thanks again for the code you have provided, it does exactly what I want it to do.
I have been testing the Moving from stack to stack, you were saying something about a minus value?
maybe the dragging up and down inteferes with moving from stack to stack?
heres a screenshot, I moved the 7 from the stack with Xvalue of 10 to the xvalue of 8 it does move accross, but the value dosent get taken from x10
I also get some sort of glitch where when i move the cursor over x9 to get to x8 it shows me a minus value in the label? any ideas?
Wednesday, June 30, 2010 7:47 AM 
It's because you have a 3D chart. The way the code selects the selected data point is different from the way it determines on top of which point the cursor is. (One is from HitTestResult.PointIndex the other is calculated from the position of the cursor.)
If change the code in the MouseDown event from
_selectedPointIndex = result.PointIndex _selectedSeries = result.Series
to
_selectedSeries = result.Series 'Find the closest point index based on the xvalue Dim xValue As Double = Math.Round(Chart1.ChartAreas(0).AxisX.PixelPositionToValue(Math.Max(Math.Min(e.X, Chart1.Size.Width  1), 0))) xValue = Math.Max(Math.Min(xValue, _selectedSeries.Points.Count), 1) _selectedPointIndex = Cint(xValue)  1
it should work in 3D. Though the data point dragging won't be as accurate as it grabs a data point even if it is behind a column. (in 2D it will work fine like this too.)
Wednesday, June 30, 2010 12:22 PMModerator 
Hi sipla I will look at applying that to the code, but I will stick with a 2D Chart for now as it works perfectly!
many thanks for all your help
regards
enex
Wednesday, June 30, 2010 1:41 PM 
Another quick question,
on a 2D Chart, When I drag the datapoints up and down and I grip the datapoint that is at the very top of the stack, Gripping right at the top (where the line is) will allow the user to adjust series data, but I want it so you can only adjust the visible series data any ideas of how i prevent this?
heres a screenshot of what i mean:
Friday, July 2, 2010 11:43 AM 
Well you could just do something like this in the MouseDown event:
If _selectedValue = 0 Then _selectedPoint = Nothing End If
Tough this way, if you drag a point to another column or set a value to zero, you have one (nonzero) value less in the chart and there's no way to get it back.
Friday, July 2, 2010 3:00 PMModerator 
hello sipla & enexooone
i want to try the code made by sipla
but when i pasted the code in the code behind (blabla.aspx.vb), i've got 1 warning said:
"namespace or type specified in the Imports 'System.Windows.Forms.DataVisualization.Charting' doesn't contain any public member or cannot be found. make sure the namespace pr the type is defined and contains at least one public member. make sure the imported element name doesn't use any aliases"
it's just the only warning,,
i'm creating a webbased application with charts right now..
please help me.
Thanks before =].
Wednesday, August 25, 2010 6:49 AM 
Hello,
This kind of interactivity only works on a Windows Forms Application, not on the web version of the chart control. There is a Silverlight chart control from Microsoft in the Silverlight Toolkit, which I assume could be used to make a web chart more interactive but I haven't tried it.
To get these examples to work, create a Windows Forms Application (make sure it has a reference to System.Windows.Forms.DataVisualization in the project properties), add a chart (with the name Chart1) to a form and paste the code to the codebehind.
Wednesday, August 25, 2010 10:24 AMModerator 
Hello. O, Ya. I thought so too yesterday. And about the Silverlight Toolkit, I'll try it. Thanks.Thursday, August 26, 2010 2:36 AM

Hi Sipla,
Another quick question
I have been binding to my stacked chart with an xValue type of string, but recently changed the xValue type to be Date.
All works well when moving the points up and down, but it wont work from side to side!, I think its a problem with the mouse move event
this line:
Dim xValue As Double = Math.Round(area.AxisX.PixelPositionToValue(Math.Max(Math.Min(e.X, Chart1.Size.Width  1), 0)))
for some reason it returns the date (OADate) instead of the pixel position?
you can see what I mean if you change the xValue type to be date
thanks in advance
enex
Tuesday, January 18, 2011 1:53 PM 
I mentioned this in one of my earlier posts. Try setting Series.IsXValueIndexed = True for each series in the chart. If you have missing data points, call the Chart.DataManipulator.InsertEmptyPoints method to align the series.
'Add data to series Dim xValues As DateTime() = {#1/1/2011#, #1/2/2011#, #1/3/2011#, #1/4/2011#, #1/5/2011#, #1/6/2011#, #1/7/2011#, #1/8/2011#, #1/9/2011#, #1/10/2011#} Dim yValues As Integer() = {2, 4, 6, 1, 5, 4, 8, 9, 4, 3} series.Points.DataBindXY(xValues, yValues) series2.Points.DataBindXY(xValues, yValues) series3.Points.DataBindXY(xValues, yValues) series.IsXValueIndexed = True series2.IsXValueIndexed = True series3.IsXValueIndexed = True 'Change the interval to whatever your data has. Chart1.ChartAreas(0).AxisX.Interval = 1 Chart1.ChartAreas(0).AxisX.IntervalType = DateTimeIntervalType.Days 'Not necessary unless you have missing data points in some of the series. Chart1.DataManipulator.InsertEmptyPoints(1, IntervalType.Days, "SERIES,SERIES2,SERIES3")
 Marked as answer by enexooone Thursday, January 20, 2011 9:49 AM
Wednesday, January 19, 2011 1:46 PMModerator 
IsXValueIndexed = True works perfectly thanks again!
Thursday, January 20, 2011 9:47 AM