簡體   English   中英

使用數據源時Datagridview拖放行

[英]Datagridview drag&drop rows when using datasource

我正在嘗試啟動並運行我的第一個應用程序,但我正在努力處理datagridview控件中的拖放操作。

我創建了一個數據網格視圖,它連接了一個數據源。

Public oBodyAssembly As New BindingList(Of BodyComponent)
DataGridView1.DataSource = oBodyAssembly

在這個DataSource 中,用戶創建新對象,這些對象顯示在datagridview 中 為了允許用戶更正或更改他添加對象的初始順序,我希望他們拖放行以重新排列對象在網格DataSource 中的位置

我已經嘗試過這個用 C# 編寫的示例代碼並將其更改為 VB.NET,它的工作原理是我可以確定拖動的行並確定放置的位置。 鏈接到示例代碼

但隨后示例中的代碼插入了一個新行並刪除了舊行。 這對我不起作用。 刪除工作正常,對象也從我的DataSource 中刪除。 另一方面,插入新行則不然。

我的數據源是一個BindingList(Of BodyComponent)它只包含從BodyComponent派生的對象。

我怎樣才能讓這個操作起作用? 我卡住了。。

這是我迄今為止用於拖放操作的代碼。

    Public oRowIndexMouseDown As Integer
Public oRow As DataGridViewRow

Private Sub BodyAssemblyDrag_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
    Handles DataGridView1.MouseDown
    If DataGridView1.SelectedRows.Count = 1 Then
        If e.Button = MouseButtons.Left Then
            oRow = DataGridView1.SelectedRows(0)
            oRowIndexMouseDown = DataGridView1.SelectedRows(0).Index
            'Debug.Print("Row to move = " & oRowIndexMouseDown)

            DataGridView1.DoDragDrop(sender, DragDropEffects.Move)
        End If
    End If
End Sub

Private Sub BodyAssemblyDrag_dragenter(ByVal sender As Object, ByVal e As DragEventArgs) Handles DataGridView1.DragEnter
    If DataGridView1.SelectedRows.Count = 1 Then
        e.Effect = DragDropEffects.Move
    End If
End Sub

Private Sub BodyAssemblyDrag_dragdrop(ByVal sender As Object, ByVal e As DragEventArgs) Handles DataGridView1.DragDrop
    Dim oPoint As Point
    oPoint = DataGridView1.PointToClient(New Point(e.X, e.Y))

    Dim oRowIndexMouseDrop As Integer
    oRowIndexMouseDrop = DataGridView1.HitTest(oPoint.X, oPoint.Y).RowIndex

    'Debug.Print("Drop row @ " & oRowIndexMouseDrop)

    If Not oRowIndexMouseDrop = oRowIndexMouseDown Then
        'DataGridView1.Rows.RemoveAt(oRowIndexMouseDown)
        'DataGridView1.Rows.Insert(oRowIndexMouseDrop, oRow)
    End If
End Sub

winform截圖

添加:在列表中創建對象的方法。

    Public oBodyAssembly As New List(Of BodyComponent)


Private Sub BTN_BODY_ADD_CILINDER_Click(sender As Object, e As EventArgs) Handles BTN_BODY_ADD_CILINDER.Click

    ' Create a new cylinder and add it into the oBodyAssembly
    Dim oCylinder As New Body_Cylinder
    oBodyAssembly.Add(oCylinder)

    ' Set the index number for this cylinder
    oCylinder.Index = oBodyAssembly.Count

    ' Set the component type
    oCylinder.Type = BodyComponent.BodyComponentType.Cylinder

End Sub

Private Sub BTN_BODY_ADD_CONE_Click(sender As Object, e As EventArgs) Handles BTN_BODY_ADD_CONE.Click

    ' Create a new cone and add it into the oBodyAssembly
    Dim oCone As New Body_Cone
    oBodyAssembly.Add(oCone)

    ' Set the index number for this cylinder
    oCone.Index = oBodyAssembly.Count

    ' Set the component type
    oCone.Type = BodyComponent.BodyComponentType.Cone_reduction

End Sub

課程:

Public Class BodyComponent

' Basic properties that are required for all of the bodycompenents
' regardless of the type.
Public Property Index() As Double
Public Property Type() As BodyComponentType
Public Property Height() As Double
Public Property Thickness() As Double
Public Property Elevation() As Double
Private Property Mass() As Double

' Type Enum that defines what kind of body component is created.
Public Enum BodyComponentType
    Cylinder = 0001
    Cone_reduction = 0002
End Enum End Class

派生對象(與錐體相同)

Public Class Body_Cylinder

' Get the base properties
Inherits BodyComponent

' Set new properties that are only required for cylinders
Public Property Segments() As Integer
Public Property LW_Orientation() As Double End Class

首先,由於無法對 BindingList 進行排序或排序(無需重新創建整個集合),我將使用帶有BindingSource的簡單List(Of T)

' Form level declarations:
Private Animals As List(Of AnimalEx)
Private BSAnimal As BindingSource

然后,一旦創建列表:

Animals = New List(Of AnimalEx)
' add Animals aka BodyComponent objects, then...
BSAnimal = New BindingSource(Animals, Nothing)
dgv.DataSource = BSAnimal

您將不得不學習一些管理數據的新方法。 從現在開始, List保存數據,但BindingSource提供綁定功能,您可以對List執行某些操作,有些則通過BindingSource


至於行拖放,這個答案中的代碼是一個很好的起點,但還缺少一些東西。 它不考慮 a) 綁定的 DGV,b) 用戶嘗試拖動 NewRow,c) 用戶單擊 DGV 的非行區域(空/打開部分) d) 允許鼠標執行其他操作,例如調整列大小。 我修復了這些問題,但可能還有其他鼠標操作需要豁免。

' Form-level declarations
Private fromIndex As Integer = -1
Private bMouseDn As Boolean = False
Private MouseDnPt As Point = Point.Empty

Private Sub dgv_DragOver(sender As Object, e As DragEventArgs) Handles dgv.DragOver
    e.Effect = DragDropEffects.Move
End Sub

Private Sub dgv_MouseDown(sender As Object, e As MouseEventArgs) Handles dgv.MouseDown
    bMouseDn = (e.Button = Windows.Forms.MouseButtons.Left)
End Sub

Private Sub dgv_MouseMove(sender As Object, e As MouseEventArgs) Handles dgv.MouseMove
    If bMouseDn Then
        ' first time, just grab the start location
        If (MouseDnPt = Point.Empty) Then
            MouseDnPt = e.Location
            Exit Sub
        End If
    End If
    If bMouseDn AndAlso MouseDnPt <> Point.Empty Then
        Dim hitTst = dgv.HitTest(e.X, e.Y)
        If hitTst IsNot Nothing AndAlso fromIndex = -1 AndAlso hitTst.RowIndex > -1 Then
            fromIndex = hitTst.RowIndex

            If dgv.Rows(fromIndex).IsNewRow = False Then
                dgv.DoDragDrop(dgv.Rows(fromIndex), DragDropEffects.Move)
            End If
        End If
    End If
End Sub

Private Sub dgv_MouseUp(sender As Object, e As MouseEventArgs) Handles dgvDD.MouseUp
    If bMouseDn AndAlso (e.Button = Windows.Forms.MouseButtons.Left) Then
        bMouseDn = False
    End If
End Sub

我用一個簡單的Point代替了Rectangle ,它測試非行區域點擊,只有在鼠標移動並按下左鍵時才開始拖動。 它也拒絕拖放 NewRow。

與原始版本一樣,它正在拖動DataGridViewRow 但是由於我們想要(必須)更改DataSource ,而不是 DGV 行,我們必須從DataSource取回項目:

Private Sub dgv_DragDrop(sender As Object, e As DragEventArgs) Handles dgv.DragDrop

    Dim p As Point = dgv.PointToClient(New Point(e.X, e.Y))
    Dim dragIndex = dgv.HitTest(p.X, p.Y).RowIndex
    If (e.Effect = DragDropEffects.Move) Then
        ' cast to a row
        Dim dragRow As DataGridViewRow = CType(e.Data.GetData(GetType(DataGridViewRow)), 
                                  DataGridViewRow)
        ' get related Animal object
        Dim a As AnimalEx = CType(dragRow.DataBoundItem, AnimalEx)

        ' manipulate DataSource:
        BSAnimal.RemoveAt(fromIndex)
        BSAnimal.Insert(dragIndex, a)

        ' if the DGV is SingleSelect, you may want:
        'dgv.Rows(dragIndex).Selected = True

        ' we are done dragging
        bMouseDn = False
        fromIndex = -1
        MouseDnPt = Point.Empty
    End If

End Sub

結果:

在此處輸入圖片說明 在此處輸入圖片說明

提到的“非行”區域是黃色區域。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM