DataGridView - ColumnOrder durch ziehen einer Zelle ändern

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von us4711.

    DataGridView - ColumnOrder durch ziehen einer Zelle ändern

    Hallo

    kann man irgendwie erreichen, dass man die Anordnung der Spalten in einem DataGridView durch ziehen/verschieben einer Zelle ändern kann? Über den ColumnHeader ist das ja möglich, ich würde aber gerne den ColumnHeader ausblenden und direkt die Zelle an eine andere Position schieben.

    Oder gibt's für mein Vorhaben auch ein Control, das für solche Sachen gedacht ist? Ich hab leider nichts gefunden und misshandle deshalb ein DGV dafür. Das funktioniert bis jetzt so:
    Ich erstelle ein DGV mit einer definierten Anzahl DataGridViewButtonColumns und genau einer Zeile. Die ColumnHeader sind standardmässig ausgeblendet, die Buttons werden ja nach Status Enabled = True/False über den Cell.Tag eingefärbt. Um nun die Reihenfolge der Einträge zu ändern drückt man die rechte Maustaste auf einer Zelle. Dabei werden die ColumnHeader eingeblendet und man kann schieben. Das DGV ist in der Höhe so eingestellt, dass beim Einblenden der ColumnHeader nur noch diese Sichtbar sind, die Buttons in der Zeile 1 jedoch nicht mehr. Schön wäre natürlich, wenn ich die Zellen direkt umherschieben könnte, statt jedes mal die ColumnHeader einzublenden. Im Anhang habe ich mal das Testprojekt hochgeladen, damit man versteht, wie es funktioniert.

    Wie gesagt, wenn es dafür ein geeigneteres Control gibt, dann her mit der Info :) Ansonsten würde mir aber auch einfach ein entsprechender Hack reichen.
    Bilder
    • Screenshot at 18-42-16.png

      4,38 kB, 672×384, 100 mal angesehen
    Dateien
    Denke ich nicht, denn das TableLayoutPanel kann ja erstmal nix ausser eine Tabelle darstellen und die Controls darin "tabellisieren". Wenn dann müsste es ein Control sein, dass für solche Drag&Drop/Move Geschichten gedacht ist. Ein solchen ist mir aber nicht bekannt bzw. kenne ich von einigen Control nicht das volle Potential.
    Ja, ist schwierig, geht aber.
    FlowLayoutPanel ist wohl einfacher:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private dragcursor As Cursor
    3. Private dragtype As Type
    4. Private Sub Form4_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    5. Me.FlowLayoutPanel1.AllowDrop = True
    6. For Each child As Control In Me.FlowLayoutPanel1.Controls
    7. AddHandler child.MouseDown, AddressOf Childs_MouseDown
    8. Next
    9. End Sub
    10. Private Sub Childs_MouseDown(sender As Object, e As MouseEventArgs)
    11. If e.Button = MouseButtons.Right Then
    12. Dim source As Control = CType(sender, Control)
    13. Using bmp As New Bitmap(source.Width, source.Height)
    14. source.DrawToBitmap(bmp, New Rectangle(Point.Empty, source.Size))
    15. Me.dragcursor = New Cursor(bmp.GetHicon)
    16. End Using
    17. Me.dragtype = source.GetType
    18. Me.FlowLayoutPanel1.DoDragDrop(source, DragDropEffects.Move)
    19. Me.dragcursor.Dispose()
    20. End If
    21. End Sub
    22. Private Sub FlowLayoutPanel1_GiveFeedback(ByVal sender As Object, ByVal e As System.Windows.Forms.GiveFeedbackEventArgs) Handles FlowLayoutPanel1.GiveFeedback
    23. e.UseDefaultCursors = False
    24. Cursor.Current = Me.dragcursor
    25. End Sub
    26. Private Sub FlowLayoutPanel1_DragDrop(sender As Object, e As DragEventArgs) Handles FlowLayoutPanel1.DragDrop
    27. Dim source As Control = CType(e.Data.GetData(dragtype), Control)
    28. Dim target As Control = Me.FlowLayoutPanel1.GetChildAtPoint(Me.FlowLayoutPanel1.PointToClient(New Point(e.X, e.Y)))
    29. If target IsNot Nothing Then
    30. Dim ix As Integer = Me.FlowLayoutPanel1.Controls.GetChildIndex(target)
    31. Me.FlowLayoutPanel1.Controls.SetChildIndex(source, ix)
    32. End If
    33. End Sub
    34. Private Sub FlowLayoutPanel1_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles FlowLayoutPanel1.DragEnter
    35. If e.AllowedEffect = DragDropEffects.Move AndAlso e.Data.GetDataPresent(dragtype) Then
    36. e.Effect = DragDropEffects.Move
    37. End If
    38. End Sub
    39. End Class

    Der Drag-Effekt wird mit der rechten Maustaste ausgelöst.
    Anbei kleines Beispiel-Projekt.
    Quelle:
    vbdotnetforums.com/gui/45818-f…repositioning-object.html
    Dateien
    @DanCooper
    Durch kleine Ergänzungen kann man einfach während des Drag-Vorganges die Mausbewegungen auf die Fläche des FlowLayoutPanels begrenzen:

    Hinzufügen:

    VB.NET-Quellcode

    1. Private Sub FlowLayoutPanel1_DragOver(sender As Object, e As EventArgs) Handles FlowLayoutPanel1.DragOver
    2. Cursor.Clip = FlowLayoutPanel1.RectangleToScreen(FlowLayoutPanel1.ClientRectangle)
    3. End Sub


    Ergänzen:

    VB.NET-Quellcode

    1. Private Sub FlowLayoutPanel1_DragDrop(sender As Object, e As DragEventArgs) Handles FlowLayoutPanel1.DragDrop
    2. Dim source As Control = CType(e.Data.GetData(dragtype), Control)
    3. Dim target As Control = Me.FlowLayoutPanel1.GetChildAtPoint(Me.FlowLayoutPanel1.PointToClient(New Point(e.X, e.Y)))
    4. If target IsNot Nothing Then
    5. Dim ix As Integer = Me.FlowLayoutPanel1.Controls.GetChildIndex(target)
    6. Me.FlowLayoutPanel1.Controls.SetChildIndex(source, ix)
    7. End If
    8. Cursor.Clip = Rectangle.Empty ' gefangenen Mouse-Cursor freigeben.
    9. End Sub