New to Telerik UI for WinForms? Download free 30-day trial

RadChartView Drag and Drop

Product Version Product Author Last modified
Q2 2013 RadChartView for WinForms Dimitar Karamfilov 09/13/2013

PROBLEM

This article demonstrates how to implement drag and drop functionality in  RadChartView. This will allow the user to move data points from one category to another. 

SOLUTION

First we will populate RadChartView with some data. In each category we have a single data point with value of 0. This is needed because all categories must remain visible despite there is no actual data in them:

BarSeries bar = new BarSeries();
bar.Name = "FakeSeries";
bar.CombineMode = ChartSeriesCombineMode.Stack;
CategoricalDataPoint point = new CategoricalDataPoint();
point.Category = "Mc1";
point.Value = 0;
bar.DataPoints.Add(point);
point = new CategoricalDataPoint();
point.Category = "Mc2";
point.Value = 0;
bar.DataPoints.Add(point);
point = new CategoricalDataPoint();
point.Category = "Mc3";
point.Value = 0;
bar.DataPoints.Add(point);
point = new CategoricalDataPoint();
point.Category = "Mc4";
point.Value = 0;
bar.DataPoints.Add(point);
point = new CategoricalDataPoint();
point.Category = "Mc5";
point.Value = 0;
bar.DataPoints.Add(point);

this.radChartView1.Series.Add(bar);
bar.IsVisibleInLegend = false;

bar = new BarSeries();
bar.Name = "Series1";
bar.CombineMode = ChartSeriesCombineMode.Stack;

point = new CategoricalDataPoint();
point.Category = "Mc1";
point.Value = 100;
bar.DataPoints.Add(point);
point = new CategoricalDataPoint();
point.Category = "Mc2";
point.Value = 200;
bar.DataPoints.Add(point);
point = new CategoricalDataPoint();
point.Category = "Mc3";
point.Value = 1000;
bar.DataPoints.Add(point);
point = new CategoricalDataPoint();
point.Category = "Mc4";
point.Value = 400;
bar.DataPoints.Add(point);

this.radChartView1.Series.Add(bar);

bar = new BarSeries();
bar.Name = "Series2";
bar.CombineMode = ChartSeriesCombineMode.Stack;

point = new CategoricalDataPoint();
point.Category = "Mc2";
point.Value = 1200;
bar.DataPoints.Add(point);
point = new CategoricalDataPoint();
point.Category = "Mc3";
point.Value = 300;
bar.DataPoints.Add(point);
point = new CategoricalDataPoint();
point.Category = "Mc4";
point.Value = 600;
bar.DataPoints.Add(point);
point = new CategoricalDataPoint();
point.Category = "Mc5";
point.Value = 120;
bar.DataPoints.Add(point);

this.radChartView1.Series.Add(bar);

bar = new BarSeries();
bar.Name = "Series3";
bar.CombineMode = ChartSeriesCombineMode.Stack;

point = new CategoricalDataPoint();
point.Category = "Mc1";
point.Value = 200;
bar.DataPoints.Add(point);
point = new CategoricalDataPoint();
point.Category = "Mc3";
point.Value = 100;
bar.DataPoints.Add(point);
point = new CategoricalDataPoint();
point.Category = "Mc4";
point.Value = 700;
bar.DataPoints.Add(point);
point = new CategoricalDataPoint();
point.Category = "Mc5";
point.Value = 430;
bar.DataPoints.Add(point);

Dim bar As BarSeries = New BarSeries()
bar.Name = "FakeSeries"
bar.CombineMode = ChartSeriesCombineMode.Stack

Dim point As CategoricalDataPoint = New CategoricalDataPoi
point.Category = "Mc1"
point.Value = 0
bar.DataPoints.Add(point)
point = New CategoricalDataPoint()
point.Category = "Mc2"
point.Value = 0
bar.DataPoints.Add(point)
point = New CategoricalDataPoint()
point.Category = "Mc3"
point.Value = 0
bar.DataPoints.Add(point)
point = New CategoricalDataPoint()
point.Category = "Mc4"
point.Value = 0
bar.DataPoints.Add(point)
point = New CategoricalDataPoint()
point.Category = "Mc5"
point.Value = 0
bar.DataPoints.Add(point)

Me.radChartView1.Series.Add(bar)
bar.IsVisibleInLegend = False

bar = New BarSeries()
bar.Name = "Series1"
bar.CombineMode = ChartSeriesCombineMode.Stack

point = New CategoricalDataPoint()
point.Category = "Mc1"
point.Value = 100
bar.DataPoints.Add(point)
point = New CategoricalDataPoint()
point.Category = "Mc2"
point.Value = 200
bar.DataPoints.Add(point)
point = New CategoricalDataPoint()
point.Category = "Mc3"
point.Value = 1000
bar.DataPoints.Add(point)
point = New CategoricalDataPoint()
point.Category = "Mc4"
point.Value = 400
bar.DataPoints.Add(point)

Me.radChartView1.Series.Add(bar)

bar = New BarSeries()
bar.Name = "Series2"
bar.CombineMode = ChartSeriesCombineMode.Stack

point = New CategoricalDataPoint()
point.Category = "Mc2"
point.Value = 1200
bar.DataPoints.Add(point)
point = New CategoricalDataPoint()
point.Category = "Mc3"
point.Value = 300
bar.DataPoints.Add(point)
point = New CategoricalDataPoint()
point.Category = "Mc4"
point.Value = 600
bar.DataPoints.Add(point)
point = New CategoricalDataPoint()
point.Category = "Mc5"
point.Value = 120
bar.DataPoints.Add(point)

Me.radChartView1.Series.Add(bar)

bar = New BarSeries()
bar.Name = "Series3"
bar.CombineMode = ChartSeriesCombineMode.Stack

point = New CategoricalDataPoint()
point.Category = "Mc1"
point.Value = 200
bar.DataPoints.Add(point)
point = New CategoricalDataPoint()
point.Category = "Mc3"
point.Value = 100
bar.DataPoints.Add(point)
point = New CategoricalDataPoint()
point.Category = "Mc4"
point.Value = 700
bar.DataPoints.Add(point)
point = New CategoricalDataPoint()
point.Category = "Mc5"
point.Value = 430
bar.DataPoints.Add(point)

Then you should subscribe to the MouseDown, DragDrop and DragOver events and also we need to enable the drop functionality for the RadChartView:

this.radChartView1.AllowDrop = true;
this.radChartView1.MouseDown += radChartView1_MouseDown;
this.radChartView1.DragDrop += radChartView1_DragDrop;
this.radChartView1.DragOver += radChartView1_DragOver;

Me.radChartView1.AllowDrop = True
AddHandler Me.radChartView1.MouseDown, AddressOf radChartView1_MouseDown
AddHandler Me.radChartView1.DragDrop, AddressOf radChartView1_DragDrop
AddHandler Me.radChartView1.DragOver, AddressOf radChartView1_DragOver

In the MouseDown event handler we need to check if the mouse is over a valid for dragging point (data point) and if it is we can perform the drag operation:

private void radChartView1_MouseDown(object sender, MouseEventArgs e)
{
    CategoricalDataPoint point = ((BarSeries)this.radChartView1.Series[0]).HitTest(e.X, e.Y) as CategoricalDataPoint;

    if (point != null)
    {
        this.radChartView1.DoDragDrop(point, DragDropEffects.Move);
    }
}

Private Sub radChartView1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)
    Dim point As CategoricalDataPoint = TryCast((CType(Me.radChartView1.Series(0), BarSeries)).HitTest(e.X, e.Y), CategoricalDataPoint)

    If Not point Is Nothing Then
        Me.radChartView1.DoDragDrop(point, DragDropEffects.Move)
    End If
End Sub

In the DragOver event handler we are preserving the move effect if the user is dragging the appropriate datatype:

void radChartView1_DragOver(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(typeof(CategoricalDataPoint)))
    {
        e.Effect = DragDropEffects.Move;
    }
}

Private Sub radChartView1_DragOver(ByVal sender As Object, ByVal e As DragEventArgs)
    If e.Data.GetDataPresent(GetType(CategoricalDataPoint)) Then
        e.Effect = DragDropEffects.Move
    End If
End Sub

Finally, we need to implement the DragDrop event handler where we are actually updating the RadChartView in order to respond to the drag and drop operation. We are checking if the mouse is over a valid drop location and then we are cloning the data points, adding it to the new series and deleting it from the old one:

void radChartView1_DragDrop(object sender, DragEventArgs e)
{
    CategoricalDataPoint point = e.Data.GetData(typeof(CategoricalDataPoint)) as CategoricalDataPoint;

    if (point != null)
    {
        CategoricalDataPoint dropPoint = null;
        Point dropLocation = this.radChartView1.PointToClient(new Point(e.X, e.Y));

        dropPoint = this.radChartView1.Series[0].HitTest(dropLocation.X, dropLocation.Y) as CategoricalDataPoint;

        if (dropPoint == null)
        {
            for (int i = 0; i < this.radChartView1.Bounds.Bottom; i++)
            {
                dropPoint = this.radChartView1.Series[0].HitTest(dropLocation.X, i) as CategoricalDataPoint;

                if (dropPoint!= null)
                {
                    break;
                }
            }
        }

        if (dropPoint != null)
        {
            BarSeries barSeries = point.Parent.Presenter as BarSeries;

            CategoricalDataPoint clone = new CategoricalDataPoint();
            clone.Category = dropPoint.Category;
            clone.Value = point.Value;
            barSeries.DataPoints.Add(clone);
            barSeries.DataPoints.Remove(point);
        }
    }
}

Private Sub radChartView1_DragDrop(ByVal sender As Object, ByVal e As DragEventArgs)
    Dim point As CategoricalDataPoint = TryCast(e.Data.GetData(GetType(CategoricalDataPoint)), CategoricalDataPoint)

    If Not point Is Nothing Then
        Dim dropPoint As CategoricalDataPoint = Nothing
        Dim dropLocation As Point = Me.radChartView1.PointToClient(New Point(e.X, e.Y))

        dropPoint = TryCast(Me.radChartView1.Series(0).HitTest(dropLocation.X, dropLocation.Y), CategoricalDataPoint)

        If dropPoint Is Nothing Then
            Dim i As Integer = 0
            Do While i < Me.radChartView1.Bounds.Bottom
                dropPoint = TryCast(Me.radChartView1.Series(0).HitTest(dropLocation.X, i), CategoricalDataPoint)

                If Not dropPoint Is Nothing Then
                    Exit Do
                End If
                i += 1
            Loop
        End If

        If Not dropPoint Is Nothing Then
            Dim barSeries As BarSeries = TryCast(point.Parent.Presenter, BarSeries)

            Dim clone As CategoricalDataPoint = New CategoricalDataPoint()
            clone.Category = dropPoint.Category
            clone.Value = point.Value
            barSeries.DataPoints.Add(clone)
            barSeries.DataPoints.Remove(point)
        End If
    End If
End Sub

In this article