This is a migrated thread and some comments may be shown as answers.

How to drag&drop between GridViews in bound mode?

16 Answers 426 Views
GridView
This is a migrated thread and some comments may be shown as answers.
xjgs_xhj@163.com
Top achievements
Rank 1
xjgs_xhj@163.com asked on 09 Oct 2010, 04:36 AM
Version:Q2 2010 SP2
The demo 'Rows Drag&Drop' works in un-bound mode but not in database bound mode.How to get it working?

16 Answers, 1 is accepted

Sort by
0
Emanuel Varga
Top achievements
Rank 1
answered on 09 Oct 2010, 07:23 AM
Hello,

In that example (unbound) whenever you perform a drop operation you have to create a new row and fill that row with data.
In bound mode you should handle the data bound item directly, removing it from one DataSource and adding it to the other data source.

private void MoveRows(RadGridView targetGrid, RadGridView dragGrid, IList<GridViewRowInfo> dragRows, int index)
{
    for (int i = dragRows.Count - 1; i >= 0; i--)
    {
        GridViewRowInfo row = dragRows[i];
        if (row is GridViewSummaryRowInfo)
        {
            continue;
        }
         
        var dataBoundItem = row.DataBoundItem;
 
        var targetCollection = (IList)targetGrid.DataSource;
        var sourceCollection = (IList)dragGrid.DataSource;
 
        sourceCollection.Remove(dataBoundItem);
        targetCollection.Insert(index, dataBoundItem);
 
        index++;
    }
 
    // if you are not using a binding list you should call a refresh on both grids
    dragGrid.Refresh();
    targetGrid.Refresh();
}

It should work like this, but if you are having any problems with it please let me know.

Best Regards,
Emanuel Varga
0
xjgs_xhj@163.com
Top achievements
Rank 1
answered on 09 Oct 2010, 10:36 AM
After just setting the DataSource property to a database BindingSource instead of using un-bound mode,I can't drag the source gridview row any more.
0
Emanuel Varga
Top achievements
Rank 1
answered on 09 Oct 2010, 09:19 PM
Hello again,

Sorry for the delayed answer, but please take a look at the following article which has a code sample on how to handle drag drop for bound grids.

If you need any more information, just let me know and i will try to provide a small sample application.

Hope this helps, if you have any other questions or comments, please let me know,

Best Regards,
Emanuel Varga
0
xjgs_xhj@163.com
Top achievements
Rank 1
answered on 10 Oct 2010, 08:29 AM
Thank you for your help.I guess it's a new feature of Q2 2010 SP2('new' tag in the demo).The article you presented to me introduces a similar way of version Q2 2010.Right?I'd like to see your application.A VB.Net sample with full fuction is perfect.
0
Emanuel Varga
Top achievements
Rank 1
answered on 10 Oct 2010, 01:43 PM
Hello again,

As promised, I've prepared an application that does Drag 'n Drop for bound grids,

Please try this example and let me know if this is everything you wanted and if everything works as expected. If everything will be OK i will create also a Code Library project with this:

VB version:
Imports System.ComponentModel
Imports Telerik.WinControls.UI
Imports Telerik.WinControls
 
''' <summary>
''' The form 1.
''' </summary>
    Partial Public Class Form1
    Inherits Form
 
#Region "Constants and Fields"
 
    ''' <summary>
    ''' The rad grid view 1.
    ''' </summary>
    Private WithEvents radGridView1 As DraggableGridView
 
    ''' <summary>
    ''' The rad grid view 2.
    ''' </summary>
    Private WithEvents radGridView2 As DraggableGridView
 
#End Region
 
#Region "Constructors and Destructors"
 
    ''' <summary>
    ''' Initializes a new instance of the <see cref="Form1"/> class.
    ''' </summary>
    Public Sub New()
        Me.InitializeComponent()
        Me.Size = New Size(600, 500)
        Me.radGridView1 = New DraggableGridView()
        Me.radGridView2 = New DraggableGridView()
    End Sub
 
#End Region
 
#Region "Methods"
 
    Private Sub Form1_Load (ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
 
        Me.radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill
        Me.Controls.Add (Me.radGridView1)
 
        Me.radGridView2.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill
        Me.Controls.Add (Me.radGridView2)
 
        Me.radGridView1.Location = New Point (0, 0)
        Me.radGridView1.Size = New Size (Me.ClientSize.Width/2, Me.ClientSize.Height)
        Me.radGridView2.Location = New Point (Me.ClientSize.Width/2, 0)
        Me.radGridView2.Size = New Size (Me.ClientSize.Width/2, Me.ClientSize.Height)
 
        Me.radGridView1.Anchor = AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Top Or AnchorStyles.Bottom
        Me.radGridView2.Anchor = AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Top Or AnchorStyles.Bottom
 
        Me.radGridView1.DataSource = New TestsCollection (10, 1)
        Me.radGridView2.DataSource = New TestsCollection (20, 10)
    End Sub
 
#End Region
End Class
 
''' <summary>
''' The draggable grid view.
''' </summary>
    Public Class DraggableGridView
    Inherits RadGridView
 
#Region "Constructors and Destructors"
 
    Dim WithEvents dragDropService As RadGridViewDragDropService
 
    ''' <summary>
    ''' Initializes a new instance of the <see cref="DraggableGridView"/> class.
    ''' </summary>
    Public Sub New()
        ' comment this line to disable multi selection
        Me.MultiSelect = True
        Me.ReadOnly = True
 
        dragDropService = Me.GridViewElement.GetService (Of RadGridViewDragDropService)()
 
        Dim gridBehavior = TryCast (Me.GridBehavior, BaseGridBehavior)
        gridBehavior.UnregisterBehavior (GetType (GridViewDataRowInfo))
        gridBehavior.RegisterBehavior (GetType (GridViewDataRowInfo), New MyGridDataRowBehavior())
    End Sub
 
#End Region
 
#Region "Properties"
 
    ''' <summary>
    ''' Gets ThemeClassName.
    ''' </summary>
    Public Overrides Property ThemeClassName() As String
        Get
            Return GetType (RadGridView).FullName
        End Get
 
        Set (ByVal value As String)
 
        End Set
    End Property
 
#End Region
 
#Region "Methods"
 
    ''' <summary>
    ''' The draggable grid view_ row formatting.
    ''' </summary>
    ''' <param name="sender">
    ''' The sender.
    ''' </param>
    ''' <param name="e">
    ''' The e.
    ''' </param>
    Private Sub DraggableGridView_RowFormatting (ByVal sender As Object, ByVal e As RowFormattingEventArgs) _
        Handles MyBase.RowFormatting
        e.RowElement.AllowDrag = True
        e.RowElement.AllowDrop = True
    End Sub
 
    ''' <summary>
    ''' The get target row index.
    ''' </summary>
    ''' <param name="row">
    ''' The row.
    ''' </param>
    ''' <param name="dropLocation">
    ''' The drop location.
    ''' </param>
    ''' <returns>
    ''' The get target row index.
    ''' </returns>
    Private Function GetTargetRowIndex (ByVal row As GridDataRowElement, ByVal dropLocation As Point) As Integer
        Dim halfHeight As Integer = row.Size.Height/2
        Dim index As Integer = row.RowInfo.Index
        If dropLocation.Y > halfHeight Then
            index += 1
        End If
 
        Return index
    End Function
 
    ''' <summary>
    ''' The move rows.
    ''' </summary>
    ''' <param name="targetGrid">
    ''' The target grid.
    ''' </param>
    ''' <param name="dragGrid">
    ''' The drag grid.
    ''' </param>
    ''' <param name="dragRows">
    ''' The drag rows.
    ''' </param>
    ''' <param name="index">
    ''' The index.
    ''' </param>
    Private Sub MoveRows (ByVal targetGrid As RadGridView, ByVal dragGrid As RadGridView, _
                          ByVal dragRows As IList(Of GridViewRowInfo), ByVal index As Integer)
        dragGrid.BeginUpdate()
        targetGrid.BeginUpdate()
 
        For i As Integer = dragRows.Count - 1 To 0 Step -1
            Dim row As GridViewRowInfo = dragRows(i)
            If TypeOf row Is GridViewSummaryRowInfo Then
                Continue For
            End If
 
            If GetType(IList).IsAssignableFrom(targetGrid.DataSource.[GetType]()) Then
                Dim targetCollection = DirectCast(targetGrid.DataSource, IList)
                Dim sourceCollection = DirectCast(dragGrid.DataSource, IList)
 
                ' handle custom removing of data bound item here if necessary
                sourceCollection.Remove(row.DataBoundItem)
 
                ' format insert data here
                targetCollection.Insert(index, row.DataBoundItem)
                ' handle custom data operations here
            Else
            End If
 
            index += 1
        Next
 
        dragGrid.EndUpdate()
        targetGrid.EndUpdate()
 
        ' if you are not using a binding list you should call a refresh on both grids
        dragGrid.Refresh()
        targetGrid.Refresh()
    End Sub
 
    ''' <summary>
    ''' The drag drop service_ preview drag drop.
    ''' </summary>
    ''' <param name="sender">
    ''' The sender.
    ''' </param>
    ''' <param name="e">
    ''' The e.
    ''' </param>
    Private Sub dragDropService_PreviewDragDrop (ByVal sender As Object, ByVal e As RadDropEventArgs) _
        Handles dragDropService.PreviewDragDrop
        e.Handled = True
 
        Dim rowElement = TryCast (e.DragInstance, GridDataRowElement)
        If rowElement Is Nothing Then
            Return
        End If
 
        Dim dropTarget = TryCast (e.HitTarget, RadItem)
        Dim targetGrid = TryCast (dropTarget.ElementTree.Control, RadGridView)
        If targetGrid Is Nothing Then
            Return
        End If
 
        Dim dragGrid = TryCast (rowElement.ElementTree.Control, RadGridView)
 
        If (targetGrid.Equals (dragGrid)) Then
            Return
        End If
 
        e.Handled = True
        Dim dropTargetRow = TryCast (dropTarget, GridDataRowElement)
        Dim _
            index As Integer = _
                If _
                (dropTargetRow IsNot Nothing, Me.GetTargetRowIndex (dropTargetRow, e.DropLocation), targetGrid.RowCount)
 
        Me.MoveRows (targetGrid, dragGrid, dragGrid.SelectedRows, index)
 
    End Sub
 
    ''' <summary>
    ''' The drag drop service_ preview drag hint.
    ''' </summary>
    ''' <param name="sender">
    ''' The sender.
    ''' </param>
    ''' <param name="e">
    ''' The e.
    ''' </param>
    Private Sub dragDropService_PreviewDragHint (ByVal sender As Object, ByVal e As PreviewDragHintEventArgs) _
        Handles dragDropService.PreviewDragHint
        Dim dataRowElement = TryCast (e.DragInstance, GridDataRowElement)
        ' set custom drag hint for multiple rows here
        'e.DragHint = new Bitmap(this.imageList1.Images[6]);
        'e.UseDefaultHint = false;
        If dataRowElement IsNot Nothing AndAlso dataRowElement.ViewTemplate.MasterTemplate.SelectedRows.Count > 1 Then
        End If
    End Sub
 
    ''' <summary>
    ''' The drag drop service_ preview drag over.
    ''' </summary>
    ''' <param name="sender">
    ''' The sender.
    ''' </param>
    ''' <param name="e">
    ''' The e.
    ''' </param>
    Private Sub dragDropService_PreviewDragOver (ByVal sender As Object, ByVal e As RadDragOverEventArgs) _
        Handles dragDropService.PreviewDragOver
        If TypeOf e.DragInstance Is GridDataRowElement Then
            e.CanDrop = TypeOf e.HitTarget Is GridDataRowElement OrElse TypeOf e.HitTarget Is GridTableElement OrElse _
                        TypeOf e.HitTarget Is GridSummaryRowElement
        End If
    End Sub
 
    ''' <summary>
    ''' The drag drop service_ preview drag start.
    ''' </summary>
    ''' <param name="sender">
    ''' The sender.
    ''' </param>
    ''' <param name="e">
    ''' The e.
    ''' </param>
    Private Sub dragDropService_PreviewDragStart (ByVal sender As Object, ByVal e As PreviewDragStartEventArgs) _
        Handles dragDropService.PreviewDragStart
        e.CanStart = True
    End Sub
 
#End Region
 
    ''' <summary>
    ''' The my grid data row behavior.
    ''' </summary>
        Private Class MyGridDataRowBehavior
        Inherits GridDataRowBehavior
 
#Region "Methods"
 
        ''' <summary>
        ''' The on mouse down left.
        ''' </summary>
        ''' <param name="e">
        ''' The e.
        ''' </param>
        ''' <returns>
        ''' The on mouse down left.
        ''' </returns>
        Protected Overrides Function OnMouseDownLeft (ByVal e As MouseEventArgs) As Boolean
            Dim dataRowElement = TryCast (Me.GetRowAtPoint (e.Location), GridDataRowElement)
 
            If dataRowElement IsNot Nothing Then
                Dim dragDropService = Me.GridViewElement.GetService (Of RadGridViewDragDropService)()
                dragDropService.Start (dataRowElement)
            End If
 
            Return MyBase.OnMouseDownLeft (e)
        End Function
 
#End Region
    End Class
End Class
 
''' <summary>
''' The test.
''' </summary>
    Public Class Test
 
#Region "Constructors and Destructors"
 
    ''' <summary>
    ''' Initializes a new instance of the <see cref="Test"/> class.
    ''' </summary>
    ''' <param name="id">
    ''' The show all.
    ''' </param>
    ''' <param name="name">
    ''' The show part.
    ''' </param>
    Public Sub New (ByVal id As Integer, ByVal name As String)
        Me.Id = id
        Me.Name = name
    End Sub
 
#End Region
 
#Region "Properties"
 
    ''' <summary>
    ''' Gets or sets ShowAll.
    ''' </summary>
    Public Property Id() As Integer
        Get
            Return m_Id
        End Get
        Set (ByVal value As Integer)
            m_Id = value
        End Set
    End Property
 
    Private m_Id As Integer
 
    ''' <summary>
    ''' Gets or sets ShowPart.
    ''' </summary>
    Public Property Name() As String
        Get
            Return m_Name
        End Get
        Set (ByVal value As String)
            m_Name = value
        End Set
    End Property
 
    Private m_Name As String
 
#End Region
End Class
 
''' <summary>
''' The tests collection.
''' </summary>
    Public Class TestsCollection
    Inherits BindingList(Of Test)
 
#Region "Constructors and Destructors"
 
    ''' <summary>
    ''' Initializes a new instance of the <see cref="TestsCollection"/> class.
    ''' </summary>
    Public Sub New (ByVal noItems As Integer, ByVal startIndex As Integer)
 
        For i As Integer = startIndex To noItems + startIndex
            Me.Add(New Test(i, "Name" + i.ToString()))
        Next
    End Sub
 
#End Region
End Class

Hope this helps, if you have any other questions or comments, please let me know,

Best Regards,
Emanuel Varga
0
xjgs_xhj@163.com
Top achievements
Rank 1
answered on 10 Oct 2010, 05:26 PM
Private Sub MoveRows(ByVal targetGrid As RadGridView, ByVal dragGrid As RadGridView, _
                          ByVal dragRows As IList(Of GridViewRowInfo), ByVal index As Integer)
.....
targetCollection.Insert(index, row.DataBoundItem)  --->run into error when binding radGridView1/radGridView2 to a same or same-structure database BindingSource.
.....
End Sub
0
Emanuel Varga
Top achievements
Rank 1
answered on 10 Oct 2010, 07:34 PM
Hello again,

Can you please give me some more information about the error / exception you have received? I tried binding the BindingLists to the grids using a BindingSource and everything works fine... .

p.s. are you using anonymous types by any chance? If you are you should switch from those to strongly typed lists, or you should handle the remove and add operations yourself, here:
Private Sub MoveRows (ByVal targetGrid As RadGridView, ByVal dragGrid As RadGridView, _
                          ByVal dragRows As IList(Of GridViewRowInfo), ByVal index As Integer)
        dragGrid.BeginUpdate()
        targetGrid.BeginUpdate()
  
        For i As Integer = dragRows.Count - 1 To 0 Step -1
            Dim row As GridViewRowInfo = dragRows(i)
            If TypeOf row Is GridViewSummaryRowInfo Then
                Continue For
            End If
  
           'handle custom operations here, search in the source collection for the data bound item for row and manually remove it and add it to the other collection
  
            index += 1
        Next
  
        dragGrid.EndUpdate()
        targetGrid.EndUpdate()
  
        ' if you are not using a binding list you should call a refresh on both grids
        dragGrid.Refresh()
        targetGrid.Refresh()
    End Sub

*Update: working with anonymous types also... so please tell me what exception are you receiving

Hope this helps, if you have any other questions or comments, please let me know,

Best Regards,
Emanuel Varga
0
xjgs_xhj@163.com
Top achievements
Rank 1
answered on 11 Oct 2010, 03:01 AM
System.ArgumentException:Cannot insert external objects to this list.

My development platform:

1.windows server 2003 sp2
2.Visual Studio 2010
3.IBM DB2 v9.1
4.GridView Q2 2010 SP2
0
Emanuel Varga
Top achievements
Rank 1
answered on 11 Oct 2010, 06:12 AM
Hello again,

This problem is not one related to telerik controls, it has more to do with limitations of some data sources.

In order for me to help you further please tell me the type of data contained in the BindingSource (DataSet, DataTable, IQueryable)?

Best Regards,
Emanuel Varga
0
xjgs_xhj@163.com
Top achievements
Rank 1
answered on 11 Oct 2010, 08:19 AM
1.System.Data.OleDb.OleDbType.[Integer]
2.System.Data.OleDb.OleDbType.BigInt
3.System.Data.OleDb.OleDbType.VarWChar
4.System.Data.OleDb.OleDbType.DBDate
5.System.Data.OleDb.OleDbType.LongVarBinary

The first column 'ID' (IDENTITY) DDL:
INTEGER NOT NULL  GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1, CACHE 20, NO CYCLE, NO ORDER)
0
Emanuel Varga
Top achievements
Rank 1
answered on 11 Oct 2010, 08:49 AM
Hello again,

This is the Item type, I was asking about the collection Type you are using the type of the object you are setting as a DataSource for the BindingSource, after you set the data source for the bindingList like:
MessageBox.Show(bindingSource1.DataSource.GetType().FullName + " " + bindingSource1.DataSource.GetType().BaseType.FullName)

Because i need to know the container collection for the items in order to tell you how you should handle this, because if you are using a DataSet, DataTable, the mechanism of creating a new Item is:
Dim row As DataRow = DataTable1.NewRow()
' populate rows cells with data
' row[""] =
' ...
' insert at the required index
DataTable1.Rows.InsertAt(row, index),

Something like this should work if you have a data table in the DataSource:
If GetType(IList).IsAssignableFrom(targetGrid.DataSource.[GetType]()) Then
    Dim targetCollection = DirectCast(targetGrid.DataSource, BindingSource)
    Dim sourceCollection = DirectCast(dragGrid.DataSource, BindingSource)
 
    Dim targetDataTable = TryCast(targetCollection.DataSource, DataTable)
 
    If targetDataTable IsNot Nothing Then
        Dim newRow = targetDataTable.NewRow()
        For j As Integer = 0 To row.Cells.Count - 1
            newRow(j) = row.Cells(j).Value
        Next
 
        targetDataTable.Rows.InsertAt(newRow, index)
    End If
 
    sourceCollection.Remove(row.DataBoundItem)
Else

Hope this helps,

Best Regards,
Emanuel Varga
0
xjgs_xhj@163.com
Top achievements
Rank 1
answered on 11 Oct 2010, 09:18 AM
I'm using the collection Type of 'System.Data.DataSet'.
0
Accepted
Emanuel Varga
Top achievements
Rank 1
answered on 11 Oct 2010, 09:39 AM
Hello again,

This should do everything you want:
Private Sub MoveRows (ByVal targetGrid As RadGridView, ByVal dragGrid As RadGridView, _
                          ByVal dragRows As IList(Of GridViewRowInfo), ByVal index As Integer)
        dragGrid.BeginUpdate()
        targetGrid.BeginUpdate()
 
        For i As Integer = dragRows.Count - 1 To 0 Step -1
            Dim row As GridViewRowInfo = dragRows(i)
            If TypeOf row Is GridViewSummaryRowInfo Then
                Continue For
            End If
 
            Dim targetCollection = DirectCast(targetGrid.DataSource, BindingSource)
            Dim sourceCollection = DirectCast(dragGrid.DataSource, BindingSource)
 
            Dim targetDataSet = TryCast(targetCollection.DataSource, DataSet)
 
            If targetDataSet IsNot Nothing Then
                Dim targetDataTable = targetDataSet.Tables("Table0")
                Dim newRow = targetDataTable.NewRow()
                For j As Integer = 0 To row.Cells.Count - 1
                    newRow(j) = row.Cells(j).Value
                Next
 
                targetDataTable.Rows.InsertAt(newRow, index)
            End If
 
            sourceCollection.Remove(row.DataBoundItem)
 
            index += 1
        Next
 
        dragGrid.EndUpdate()
        targetGrid.EndUpdate()
 
        ' if you are not using a binding list you should call a refresh on both grids
        dragGrid.Refresh()
        targetGrid.Refresh()
    End Sub

Because the data source was a data set, you have to get the required table, and create a new row for that table, and after that insert at that position.

Best Regards,
Emanuel Varga
0
xjgs_xhj@163.com
Top achievements
Rank 1
answered on 11 Oct 2010, 10:04 AM
Great!That's what I'm waiting for.I'll try 'hierarchical drag&drop' and 'rows reorder' features with this.Thank you very much.
0
Emanuel Varga
Top achievements
Rank 1
answered on 11 Oct 2010, 12:26 PM
Hello again,

I'm glad to hear that this works for you, if everything is OK, please mark the answer to the question so that others can find their answer quicker if they are searching for a way of implementing drag & drop for bounded grids.

If you have any other questions, please let me know.

Best Regards,
Emanuel Varga
0
Brahim
Top achievements
Rank 1
answered on 13 Nov 2010, 03:32 AM
Hi
like xjgs_xhj@163.com I'm using a dataset and the above code worked perfectly. I was just wondering how you would go about modifying the code to allow for multiple selected items?

thanks in advance
Tags
GridView
Asked by
xjgs_xhj@163.com
Top achievements
Rank 1
Answers by
Emanuel Varga
Top achievements
Rank 1
xjgs_xhj@163.com
Top achievements
Rank 1
Brahim
Top achievements
Rank 1
Share this question
or