DragDrop mit DataGridViewCustomCell

  • VB.NET

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von Hajo.

    DragDrop mit DataGridViewCustomCell

    Hallo zusammen,

    folgende Problematik beschäftigt mich:
    Ich habe mehrere CustomCells in einer DataGridView und ziehe diese per DragDrop in eine andere DataGridView. Prinzipiell funktioniert das, allerdings spricht der DragDrop Vorgang nur in einem kleinen Bereich der Zelle an. Im Bild ist dieser Bereicht markiert. In allen anderen Bereichen der Zelle funktioniert das DragDrop nicht.

    Meine CustomCell basiert auf einer DataGridViewImageCell:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Drawing
    2. Imports System.ComponentModel
    3. Public Class DataGridViewDriveColumn
    4. Inherits DataGridViewImageColumn
    5. Public Sub New()
    6. Me.CellTemplate = New DataGridViewDriveCell
    7. End Sub
    8. End Class
    9. Public Class DataGridViewDriveCell
    10. Inherits DataGridViewImageCell
    11. Private myFolderSize As Long
    12. Public Property FolderSize() As Long
    13. Get
    14. Return myFolderSize
    15. End Get
    16. Set(ByVal Value As Long)
    17. myFolderSize = Value
    18. End Set
    19. End Property
    20. Private myDriveObject As DriveObject
    21. Public Property DriveObject() As DriveObject
    22. Get
    23. Return myDriveObject
    24. End Get
    25. Set(ByVal Value As DriveObject)
    26. myDriveObject = Value
    27. End Set
    28. End Property
    29. ''' <summary>
    30. ''' Neuinstanzierung
    31. ''' </summary>
    32. ''' <remarks></remarks>
    33. Sub New()
    34. ValueType = Type.GetType("String")
    35. myFolderSize = 0
    36. myDriveObject = New DriveObject
    37. End Sub
    38. ''' <summary>
    39. ''' Method required to make the Cell consistent with the default Image Cell.
    40. ''' The default Image Cell assumes an Image as a value, although the value of the Progress Cell is an Integer.
    41. ''' </summary>
    42. ''' <param name="value"></param>
    43. ''' <param name="rowIndex"></param>
    44. ''' <param name="cellStyle"></param>
    45. ''' <param name="valueTypeConverter"></param>
    46. ''' <param name="formattedValueTypeConverter"></param>
    47. ''' <param name="context"></param>
    48. ''' <returns></returns>
    49. ''' <remarks></remarks>
    50. Protected Overrides Function GetFormattedValue( _
    51. ByVal value As Object, _
    52. ByVal rowIndex As Integer, _
    53. ByRef cellStyle As DataGridViewCellStyle, _
    54. ByVal valueTypeConverter As TypeConverter, _
    55. ByVal formattedValueTypeConverter As TypeConverter, _
    56. ByVal context As DataGridViewDataErrorContexts _
    57. ) As Object
    58. Static emptyImage As Bitmap = New Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
    59. GetFormattedValue = emptyImage
    60. End Function
    61. ''' <summary>
    62. ''' Zeichnet das Control
    63. ''' </summary>
    64. ''' <param name="g"></param>
    65. ''' <param name="clipBounds"></param>
    66. ''' <param name="cellBounds"></param>
    67. ''' <param name="rowIndex"></param>
    68. ''' <param name="cellState"></param>
    69. ''' <param name="value"></param>
    70. ''' <param name="formattedValue"></param>
    71. ''' <param name="errorText"></param>
    72. ''' <param name="cellStyle"></param>
    73. ''' <param name="advancedBorderStyle"></param>
    74. ''' <param name="paintParts"></param>
    75. ''' <remarks></remarks>
    76. Protected Overrides Sub Paint(ByVal g As System.Drawing.Graphics, _
    77. ByVal clipBounds As System.Drawing.Rectangle, _
    78. ByVal cellBounds As System.Drawing.Rectangle, _
    79. ByVal rowIndex As Integer, _
    80. ByVal cellState As System.Windows.Forms.DataGridViewElementStates, _
    81. ByVal value As Object, _
    82. ByVal formattedValue As Object, _
    83. ByVal errorText As String, _
    84. ByVal cellStyle As System.Windows.Forms.DataGridViewCellStyle, _
    85. ByVal advancedBorderStyle As System.Windows.Forms.DataGridViewAdvancedBorderStyle, _
    86. ByVal paintParts As System.Windows.Forms.DataGridViewPaintParts)
    87. Dim myForeBrush As Brush = New SolidBrush(cellStyle.ForeColor)
    88. Dim myIconWidth As Integer = 32
    89. 'Zeichnet die Standardansicht der Zelle
    90. MyBase.Paint(g, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, _
    91. advancedBorderStyle, paintParts)
    92. 'Icon
    93. g.DrawImage(My.Resources.drive, New Point(cellBounds.X + 18, cellBounds.Y + 6))
    94. 'Text
    95. g.DrawString("(" & myDriveObject.DriveName & ") " & myDriveObject.VolumeLabel, cellStyle.Font, myForeBrush, _
    96. cellBounds.X + 18 + myIconWidth + 6, cellBounds.Y + 15)
    97. End Sub
    98. End Class


    Und noch eine andere Sache zum Thema DragDrop: Zieht man beispielsweise bei Firefox ein Bild mit der Maus, folgt das Bild der Maus. Gibt es hierzu einen Lösungsansatz für die DataGridViewColumn?

    Vielen Dank für jegliche Anregungen,
    Hajo
    Bilder
    • 01.png

      19,01 kB, 782×448, 171 mal angesehen
    Ich denke, das Drop funktioniert genau da nicht, wo DataGridViewDriveCell.Paint() hinmalt.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hast Du vielleicht ein wenig mehr Code zum testen?
    (Drag...)
    Z.B. bekomme ich den Inhalt von DriveObject nicht angezeigt.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Habe den Code etwas reduziert und nur die für die Problematik wichtigen Stellen übrig gelassen. Die Funktionalität bleibt erhalten.

    Das Programm kopiert nachts Daten an von mir bestimmte Kopierziele. Dafür ziehe ich die Ordner, die ich kopiert haben möchte aus dem Explorer in die DGV. Per DragDrop ziehe ich die Spalte der DGV auf die Zelle der zweiten DGV, in der die Laufwerke aufgelistet sind. Auf diese Art weise ich das Kopierziel zu.
    Das DriveObject enthält den Laufwerksbuchstabe, die Laufwerksbezeichnung und den Freien Speicherplatz der Ziellaufwerke.

    //Vielen Dank für Dein Interesse!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Hajo“ ()

    VS 2010, ich hab 2008.
    Option Strict = Off ???
    Die Assemblies MAPI und Outlook braucht er nicht (hat er nämlich nicht gefunden.
    So. Läuft erst mal. :rolleyes:
    An welcher Stelle machst Du Drag-Drop mit DGV-Zellen?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    VS 2010, ich hab 2008.
    Option Strict = Off ???
    Die Assemblies MAPI und Outlook braucht er nicht (hat er nämlich nicht gefunden.
    So. Läuft erst mal. :rolleyes:
    An welcher Stelle machst Du Drag-Drop mit DGV-Zellen?
    Guter Einwand, werde ich ändern Option Strict = On.
    Die Assemblies braucht er nicht, weil ich den Code ja reduziert habe. Mein vollständiger Code benötigt diese natürlich.

    Der Code für das DragDrop ist in der Form1. Allerdings wird die ganze Spalte davon angesprochen:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub DGV_CellMouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles DGV.CellMouseDown
    2. Dim myHittest As DataGridView.HitTestInfo = Me.DGV.HitTest(e.X, e.Y)
    3. If myHittest.RowIndex >= 0 Then
    4. Me.DGV.DoDragDrop(Me.DGV.Rows(myHittest.RowIndex), DragDropEffects.Copy)
    5. End If
    6. End Sub
    7. Private Sub DGV_Drives_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles DGV_Drives.DragDrop
    8. Dim clientPoint As Point = Me.DGV_Drives.PointToClient(New Point(e.X, e.Y))
    9. Dim myHittest As DataGridView.HitTestInfo = Me.DGV_Drives.HitTest(clientPoint.X, clientPoint.Y)
    10. Dim myType As Type = GetType(DataGridViewRow)
    11. Dim r As DataGridViewRow = Me.DGV.CurrentRow
    12. If myHittest.RowIndex = -1 Then
    13. Exit Sub
    14. End If
    15. Dim myCell As DataGridViewBlurayCell
    16. Dim myDriveCell As DataGridViewDriveCell
    17. If TypeOf r.Cells(0) Is DataGridViewBlurayCell Then
    18. If TypeOf (Me.DGV_Drives.Rows(myHittest.RowIndex).Cells(0)) Is DataGridViewDriveCell Then
    19. myCell = r.Cells(0)
    20. myDriveCell = Me.DGV_Drives.Rows(myHittest.RowIndex).Cells(0)
    21. myCell.DriveObject = myDriveCell.DriveObject
    22. Dim myDriveCell2 As DataGridViewDriveCell
    23. myDriveCell2 = Me.DGV.CurrentRow.Cells(1)
    24. myDriveCell2.DriveObject = myCell.DriveObject
    25. End If
    26. End If
    27. Me.DGV.Refresh()
    28. End Sub
    29. Private Sub DGV_Drives_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles DGV_Drives.DragEnter
    30. e.Effect = DragDropEffects.Copy
    31. End Sub
    Den Code habe ich gesehen.
    Welche Bedingungen müssen erfüllt sein, damit ich "draggen" kann?
    (DGV_CellMouseDown())

    Noch eine Bemerkung zum Stil:
    Funktionen geben Werte mit Return zurück.
    Das Verwenden des Funktionsnamens ist veraltet.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich kann klicken und ziehen, aber ich kann das "Me.DGV.DoDragDrop()" nicht reproduzierbar auslösen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    OK.
    Wichtig ist, und das war ja Dein Problem, dass nur in einem schmalen Bereich geklickt werden kann.

    Anmerkung:
    Ich habe 2 Pfade reingezogen, es wird immer die falsche DGV-Zeile aktualisiert.

    ===========================================================
    Ich glaube, dass "Me.DGV.HitTest()" Mist macht.
    Ändere die Zeile um in:

    VB.NET-Quellcode

    1. Dim myHittest As DataGridView.HitTestInfo = Me.DGV.HitTest(70, 40) 'e.X, e.Y)

    und es läuft. :D
    (70 und 40 sind ausprobierte Werte)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „RodFromGermany“ ()

    RodFromGermany schrieb:

    Ich glaube, dass "Me.DGV.HitTest()" Mist macht.
    Ja, in der Tat ist das so.

    Ich habs jetzt mit folgendem Code gelöst. Nicht ganz so schön, aber immerhin spricht nun die ganze Zelle/Zeile darauf an.
    Herzlichen Dank für Deine Hilfe und Mühe.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub DGV_CellMouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles DGV.CellMouseDown
    2. Dim myRect As Rectangle
    3. myRect = Me.DGV.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, False)
    4. Dim myMouseRect As Rectangle
    5. myMouseRect = New Rectangle(New Point(e.X + myRect.Location.X, e.Y + myRect.Location.Y), New Size(1, 1))
    6. If myRect.IntersectsWith(myMouseRect) Then
    7. Me.DGV.DoDragDrop(Me.DGV.Rows(e.RowIndex), DragDropEffects.Copy)
    8. End If
    9. End Sub