Imports System.Collections.Generic
Imports System.Linq
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports Telerik.Web.UI
Imports System.Data
Imports System.Configuration
Imports System.Data.Common
Imports System.Data.SqlClient

Partial Public Class DragAndDropVB
    Inherits System.Web.UI.Page


    Protected Sub UseDragColumnCheckBox_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs)
        grdPendingOrders.MasterTableView.GetColumn("DragDropColumn").Visible = UseDragColumnCheckBox.Checked
        grdPendingOrders.Rebind()

        grdShippedOrders.MasterTableView.GetColumn("DragDropColumn").Visible = UseDragColumnCheckBox.Checked
        grdShippedOrders.Rebind()
    End Sub

    Protected Property PendingOrdersStore() As IList(Of Order)
        Get
            Try
                Dim obj As Object = Session("PendingOrders_VB")
                If obj Is Nothing Then
                    obj = GetOrders()
                    Session("PendingOrders_VB") = obj
                End If
                Return DirectCast(obj, IList(Of Order))
            Catch ex As Exception
                Session("PendingOrders_VB") = Nothing
            End Try
            Return New List(Of Order)
        End Get
        Set(ByVal value As IList(Of Order))
            Session("PendingOrders_VB") = value
        End Set
    End Property

    Protected Property ShippedOrdersStore() As IList(Of Order)
        Get
            Try
                Dim obj As Object = Session("ShippedOrders_VB")
                If obj Is Nothing Then
                    obj = New List(Of Order)()
                    Session("ShippedOrders_VB") = obj
                End If
                Return DirectCast(obj, IList(Of Order))
            Catch ex As Exception
                Session("ShippedOrders_VB") = Nothing
            End Try
            Return New List(Of Order)
        End Get
        Set(ByVal value As IList(Of Order))
            Session("ShippedOrders_VB") = value
        End Set
    End Property

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
    End Sub

    Protected Sub grdPendingOrders_NeedDataSource(ByVal source As Object, ByVal e As GridNeedDataSourceEventArgs)
        grdPendingOrders.DataSource = PendingOrdersStore
    End Sub

    Protected Function GetOrders() As IList(Of Order)
        Dim results As IList(Of Order) = New List(Of Order)()
        Using connection As IDbConnection = DbProviderFactories.GetFactory("System.Data.SqlClient").CreateConnection()
            connection.ConnectionString = ConfigurationManager.ConnectionStrings("NorthwindConnectionString").ConnectionString

            Using command As IDbCommand = connection.CreateCommand()
                command.CommandText = "SELECT o.OrderID, o.CustomerID, o.RequiredDate, c.CompanyName FROM orders o INNER JOIN customers c on o.customerID = c.customerID"

                connection.Open()
                Try
                    Dim reader As IDataReader = command.ExecuteReader()
                    While reader.Read()
                        Dim id As Integer = DirectCast(reader.GetValue(reader.GetOrdinal("OrderID")), Integer)
                        Dim customerID As String = IIf((Not reader.IsDBNull(reader.GetOrdinal("CustomerID"))), DirectCast(reader.GetValue(reader.GetOrdinal("CustomerID")), String), String.Empty)
                        Dim requiredDate As DateTime = IIf((Not reader.IsDBNull(reader.GetOrdinal("RequiredDate"))), DirectCast(reader.GetValue(reader.GetOrdinal("RequiredDate")), DateTime), DateTime.MinValue)
                        Dim companyName As String = IIf((Not reader.IsDBNull(reader.GetOrdinal("CompanyName"))), Server.HtmlEncode(DirectCast(reader.GetValue(reader.GetOrdinal("CompanyName")), String)), String.Empty)
                        results.Add(New Order(id, customerID, companyName, requiredDate))
                    End While
                Catch ex As SqlException
                    results.Clear()
                End Try
            End Using
        End Using
        Return results
    End Function

    Protected Sub grdShippedOrders_NeedDataSource(ByVal source As Object, ByVal e As GridNeedDataSourceEventArgs)
        grdShippedOrders.DataSource = ShippedOrdersStore
    End Sub

    Protected Sub grdPendingOrders_RowDrop(ByVal sender As Object, ByVal e As GridDragDropEventArgs)
        If String.IsNullOrEmpty(e.HtmlElement) Then
            If e.DraggedItems(0).OwnerGridID = grdPendingOrders.ClientID Then
                ' items are drag from pending to shipped grid
                If (e.DestDataItem Is Nothing AndAlso ShippedOrdersStore.Count = 0) OrElse (e.DestDataItem IsNot Nothing AndAlso e.DestDataItem.OwnerGridID = grdShippedOrders.ClientID) Then
                    Dim shippedOrders As IList(Of Order)
                    Dim pendingOrders As IList(Of Order)

                    shippedOrders = ShippedOrdersStore
                    pendingOrders = PendingOrdersStore

                    Dim destinationIndex As Int32 = -1
                    If (e.DestDataItem IsNot Nothing) Then
                        Dim order As Order = GetOrder(shippedOrders, DirectCast(e.DestDataItem.GetDataKeyValue("OrderId"), Integer))
                        destinationIndex = IIf(order IsNot Nothing, shippedOrders.IndexOf(order), -1)
                    End If

                    For Each draggedItem As GridDataItem In e.DraggedItems
                        Dim tmpOrder As Order = GetOrder(pendingOrders, DirectCast(draggedItem.GetDataKeyValue("OrderId"), Integer))

                        If tmpOrder IsNot Nothing Then
                            If destinationIndex > -1 Then
                                If e.DropPosition = GridItemDropPosition.Below Then
                                    destinationIndex += 1
                                End If
                                shippedOrders.Insert(destinationIndex, tmpOrder)
                            Else
                                shippedOrders.Add(tmpOrder)
                            End If
                            pendingOrders.Remove(tmpOrder)
                        End If
                    Next

                    ShippedOrdersStore = shippedOrders
                    PendingOrdersStore = pendingOrders
                    grdPendingOrders.Rebind()
                    grdShippedOrders.Rebind()
                ElseIf e.DestDataItem IsNot Nothing AndAlso e.DestDataItem.OwnerGridID = grdPendingOrders.ClientID Then

                    'reorder items in pending grid
                    Dim pendingOrders As IList(Of Order)
                    pendingOrders = PendingOrdersStore

                    Dim order As Order = GetOrder(pendingOrders, DirectCast(e.DestDataItem.GetDataKeyValue("OrderId"), Integer))
                    Dim destinationIndex As Integer = pendingOrders.IndexOf(order)

                    If ((e.DropPosition = GridItemDropPosition.Above) _
                            AndAlso (e.DestDataItem.ItemIndex > e.DraggedItems(0).ItemIndex)) Then
                        destinationIndex = (destinationIndex - 1)
                    End If
                    If ((e.DropPosition = GridItemDropPosition.Below) _
                            AndAlso (e.DestDataItem.ItemIndex < e.DraggedItems(0).ItemIndex)) Then
                        destinationIndex = (destinationIndex + 1)
                    End If

                    Dim ordersToMove As New List(Of Order)()
                    For Each draggedItem As GridDataItem In e.DraggedItems
                        Dim tmpOrder As Order = GetOrder(pendingOrders, DirectCast(draggedItem.GetDataKeyValue("OrderId"), Integer))
                        If tmpOrder IsNot Nothing Then
                            ordersToMove.Add(tmpOrder)
                        End If
                    Next

                    For Each orderToMove As Order In ordersToMove
                        pendingOrders.Remove(orderToMove)
                        pendingOrders.Insert(destinationIndex, orderToMove)
                    Next
                    PendingOrdersStore = pendingOrders
                    grdPendingOrders.Rebind()

                    Dim destinationItemIndex As Integer = destinationIndex - (grdPendingOrders.PageSize * grdPendingOrders.CurrentPageIndex)
                    e.DestinationTableView.Items(destinationItemIndex).Selected = True
                End If
            End If
        End If
    End Sub

    Private Shared Function GetOrder(ByVal ordersToSearchIn As IEnumerable(Of Order), ByVal orderId As Integer) As Order
        For Each order As Order In ordersToSearchIn
            If order.OrderID = orderId Then
                Return order
            End If
        Next
        Return Nothing
    End Function

    Protected Sub grdShippedOrders_RowDrop(ByVal sender As Object, ByVal e As GridDragDropEventArgs)
        If Not String.IsNullOrEmpty(e.HtmlElement) AndAlso e.HtmlElement = "trashCan" Then
            Dim shippedOrders As IList(Of Order)
            shippedOrders = ShippedOrdersStore
            Dim deleted As Boolean = False

            For Each draggedItem As GridDataItem In e.DraggedItems
                Dim tmpOrder As Order = GetOrder(shippedOrders, DirectCast(draggedItem.GetDataKeyValue("OrderId"), Integer))

                If tmpOrder IsNot Nothing Then
                    deleted = True
                    shippedOrders.Remove(tmpOrder)
                End If
            Next
            If (deleted) Then
                msg.Visible = True
            End If
            ShippedOrdersStore = shippedOrders
            grdShippedOrders.Rebind()
        End If
    End Sub



    Protected Class Order
        Private _companyName As String
        Private _customerId As String
        Private _orderId As Integer
        Private _requiredDate As DateTime

        Public Sub New(ByVal orderId As Integer, ByVal customerId As String, ByVal companyName As String, ByVal requiredDate As DateTime)
            _orderId = orderId
            _customerId = customerId
            _companyName = companyName
            _requiredDate = requiredDate
        End Sub

        Public ReadOnly Property OrderID() As Integer
            Get
                Return _orderId
            End Get
        End Property

        Public ReadOnly Property CustomerID() As String
            Get
                Return _customerId
            End Get
        End Property

        Public ReadOnly Property Company() As String
            Get
                Return _companyName
            End Get
        End Property

        Public ReadOnly Property RequiredDate() As DateTime
            Get
                Return _requiredDate
            End Get
        End Property
    End Class

End Class