Vb.net Datagridview拖放&;使用数据源时删除行

Vb.net Datagridview拖放&;使用数据源时删除行,vb.net,datagridview,drag-and-drop,datasource,Vb.net,Datagridview,Drag And Drop,Datasource,我正试图启动并运行我的第一个应用程序,但我在datagridview控件中进行拖放操作 我已经创建了一个datagrid视图,其中连接了一个数据源 Public oBodyAssembly As New BindingList(Of BodyComponent) DataGridView1.DataSource = oBodyAssembly 在此数据源中用户创建新的对象,这些对象显示在数据网格视图中。为了允许用户更正或更改其添加对象的初始顺序,我希望让它们拖放行,以重新排列对象在网格和数据源

我正试图启动并运行我的第一个应用程序,但我在datagridview控件中进行拖放操作

我已经创建了一个datagrid视图,其中连接了一个数据源

Public oBodyAssembly As New BindingList(Of BodyComponent)
DataGridView1.DataSource = oBodyAssembly
在此数据源中用户创建新的对象,这些对象显示在数据网格视图中。为了允许用户更正或更改其添加对象的初始顺序,我希望让它们拖放行,以重新排列对象在网格和数据源中的位置

我已经尝试了这个用C#编写的示例代码,并将其修改为VB.NET,它的工作原理是我可以确定拖动的行和放置的位置。

但是,示例中的代码插入新行并删除旧行。这对我不管用。删除工作正常,对象也会从my数据源中删除。另一方面,插入新行不起作用

Mydatasource是一个
BindingList(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

添加:在列表中创建对象的方法

    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
衍生对象(与圆锥体相同)


首先,由于BindingList无法排序或排序(如果不重新创建整个集合),因此我将使用一个简单的
List(Of T)
BindingSource

' Form level declarations:
Private Animals As List(Of AnimalEx)
Private BSAnimal As BindingSource
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
然后,创建列表后:

Animals = New List(Of AnimalEx)
' add Animals aka BodyComponent objects, then...
BSAnimal = New BindingSource(Animals, Nothing)
dgv.DataSource = BSAnimal
您必须学习一些新的方法来管理数据。从现在起,
列表
保存数据,但
BindingSource
提供绑定功能,您可以对
列表
执行一些操作,也可以通过
BindingSource
执行一些操作


至于行拖放,中的代码是一个不错的起点,但还缺少一些东西。它不考虑a)绑定DGV,b)用户尝试拖动新行,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
结果:


提到的“非行”区域是淡黄色区域。

您将需要一个不同的集合。不能对绑定列表进行排序或重新排序。您确定要在鼠标按下时启动DargDrop吗?谢谢您的快速回复,您建议使用什么集合?我不太熟悉收藏的类型。。不,它不应该在鼠标按下时启动拖动。它应该向下移动吗?但是我以前从来没有做过这样的事情,我知道怎么写。嗨,我现在正在尝试这个列表,但是它不适合我,正如我所希望的那样。创建数据绑定时,
Public obodysassembly As List(BodyComponent的)Private BSAnimal As BindingSource Public Sub New(),设计器需要此调用。InitializeComponent()'将程序集添加到车身网格。oBodyAssembly=新列表(BodyComponent的)BSAnimal=新BindingSource(oBodyAssembly,Nothing)DataGridView1.DataSource=BSAnimal End Sub
,然后将一个新对象添加到列表(Of…)中,它在dgv中不可见?从未格式化的代码中可以看出,列表中没有任何项。请注意,答案将在列表包含项之后设置DGV数据源。BindingSource“填充”了您在BindingList中的一些角色。使用
BSAnimal.Add(带有{…}的新AnimalEx)
将项目添加到列表/bindingsource好的,我添加了用于在列表中创建项目的代码,但是现在我得到了它,如果我通过bindingsource添加项目,它会起作用。正如你在我编辑的帖子中看到的,我直接将它们添加到我的列表中。实际上,它最终会出现在列表中,你只需要通过BS,这样它就可以意识到更新UI。我想你在编辑时不小心没有包括鼠标向上事件?
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