DatagridView im Edit Mode - Ereignisse abfangen

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

Es gibt 26 Antworten in diesem Thema. Der letzte Beitrag () ist von Peter329.

    Hi,

    inzwischen habe ich eine Idee, die mir sehr viel einfacher zu sein scheint.

    Ich verlagere die Verarbeitung von ENTER und RETURN einfach in die Routine ProcessCmdKey !

    Denn diese Routine wird in jedem Fall angesprungen. Und das unabhängig davon in welchem Zustand die dgv sich befindet (edit mode, non-edit mode).

    VB.NET-Quellcode

    1. Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message,
    2. ByVal keyData As System.Windows.Forms.Keys) As Boolean
    3. If msg.Msg = WM_KEYDOWN AndAlso msg.WParam.ToInt32 = Keys.Return Then
    4. Ex = ((msg.LParam.ToInt32() And KF_EXTENDED) = KF_EXTENDED)
    5. If Ex Then
    6. Debug.Print("ProcessCmdKey --> ENTER key was depressed")
    7. 'Process ENTER key ...
    8. Else
    9. Debug.Print("ProcessCmdKey --> RETURN key was depressed")
    10. 'Process RETURN key ...
    11. End If
    12. Return MyBase.ProcessCmdKey(msg, keyData)


    Das löst fast mein Problem.

    Dumm ist nur, dass NACH dem Ende der ProcessCmdKey Routine, dann noch dgv Events ausgelöst werden. Denn im "edit mode", wird nun noch die nächste Zeile selektiert. Und das kollidiert mit meiner Verarbeitung.

    Quellcode

    1. ProcessCmdKey --> ENTER key was depressed (hier passiert die Verarbeitung)
    2. dgvEdit CurrentCellChanged (jetzt schlägt der Vorschub des Zeilencursors zu ! )
    3. dgvEdit CellEnter
    4. CellClickEnter


    Wenn ich also verhindern könnte, dass im "edit mode" mit ENTER bzw. RETURN die nächste Zeile ausgewählt wird, wäre ich vollkommen happy !

    Kann man in der ProcessCmdKey Routine ENTER bzw. RETURN als "handled" kennzeichnen. Ich hab mal ganz frech die Routine mit "Return False" beendet, aber das hilft leider nicht.

    Ansonsten könnte vielleicht die Sache mit der abgeleiteten dgv weiter helfen. Vielleicht kann man ja eine Spalte so definieren, dass der edit mode, sich nicht in die Zeilensteuerung einmischt. Aber dazu fehlen mir wohl die Kenntnisse.

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Peter329“ ()

    VB.NET-Quellcode

    1. If msg.Msg = WM_KEYDOWN AndAlso msg.WParam.ToInt32 = Keys.Return Then
    2. Ex = ((msg.LParam.ToInt32() And KF_EXTENDED) = KF_EXTENDED)
    3. If Ex Then
    4. Debug.Print("ProcessCmdKey --> ENTER key was depressed")
    5. 'Process ENTER key ...
    6. Else
    7. Debug.Print("ProcessCmdKey --> RETURN key was depressed")
    8. 'Process RETURN key ...
    9. End If
    10. Return Nothing
    11. Else
    12. Return MyBase.ProcessCmdKey(msg, keyData)
    13. End If

    Vielleicht reicht das Return Nothing ja aus, um weitere Verarbeitung zu unterdrücken?

    us4711 schrieb:

    berichte


    Fortschritt: TestBereit.

    Ich haenge einfach mal die bereinigte Projektmappe an. @us4711, vllt. mach ich dazu mal einen Thread auf, aber erstmal fertig sein.

    Edit @Peter329

    Um das in deinem Projekt testen zu koennen, fuege die Klassen
    -DataGridViewColumnEx
    -DataGridViewTextBoxCellEx
    -DataGridViewTextBoxEditingControlEx
    deinem Projekt hinzu, einmal debuggen, dann kannst du im Designer den Column-Typen in der Columns-Property der DGV einstellen, also anstatt DataGridViewTextBoxColumn, DataGridViewColumnEx. Das EditingControl hat nun ein Event Namens EnterOrReturn welches abboniert werden muss, statt PreviewKeyDown.
    Dateien
    And i think to myself... what a wonderfuL World!

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

    @Peter329
    Ja, das geht so natürlich viel einfacher. Du sparst Dir den ganzen Aufwand mit Addhandler und so.
    Und wegen der abschliessenden Behandlung: Manchmal ist ja doch ein Blick in die Dokumentation sinnreich (seufz):

    VB.NET-Quellcode

    1. Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
    2. If msg.Msg = WM_KEYDOWN AndAlso msg.WParam.ToInt32 = Keys.Return Then
    3. If (msg.LParam.ToInt32() And KF_EXTENDED) = KF_EXTENDED Then
    4. Debug.WriteLine("Enter")
    5. Else
    6. Debug.WriteLine("Return")
    7. End If
    8. Return True
    9. Else
    10. Return False
    11. End If
    12. End Function

    Return False bedeutet, Tastendruck nicht abschliessend bearbeitet
    Return True Alles erledigt, weitere Aktionen werden unterdrückt.
    Der Rückgabewert der Function (Boolean) hätte etwas ähnliches andeuten sollen. Ich war wohl gestern aband doch zu lange im Garten beim Wein ..
    @Eddy
    Schöne Lösung für die eigene DataGridViewColumn.
    Das mit dem Return-Value (s. oben) geht da auch

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

    us4711 schrieb:

    Manchmal ist ja doch ein Blick in die Dokumentation sinnreich (seufz):


    OMG, manchmal sieht man den Wald vor lauter Bäumen nicht, das war eigendlich offensichtlich. X/


    Edit @Peter329 @us4711

    Im Code fehlt noch etwas wichtiges, hatte mich gerade gewundert warum die Zelle nach dem Editieren leer war, diese Methode muss unbedingt noch in die Klasse DataGridViewTextBoxEditingControlEx rein.

    VB.NET-Quellcode

    1. Protected Overrides Sub OnTextChanged(ByVal eventargs As EventArgs)
    2. valueIsChanged = True
    3. Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
    4. MyBase.OnTextChanged(eventargs)
    5. End Sub


    And i think to myself... what a wonderfuL World!

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Eddy“ ()

    Hi,

    jau, das mit dem Return = True für den Abschluss der Tastendruck Bearbeitung klappt hervorragend ! Da hätte ich tatsächlich erst mal in die Doku gucken sollen !

    Die Sache mit der selbst definierten Spalte in der dgv ist natürlich ein Leckerbissen ! Ich hab das jetzt herunter geladen und werde das in Ruhe ausprobieren !

    Erst mal ein herzlichen Danke an alle Ratgeber ! Ich habe eine Menge gelernt !

    LG
    Peter
    Also zusammenfassend: mit dem Ergebnis bin ich SUPER zufrieden ! Das Ganze funktioniert soweit genauso, wie ich es mir vorgestellt habe.

    Weil die ProcessCmdKey Routine super nützlich aber vielleicht nicht jedem auf Anhieb verständlich ist, habe ich mal ein paar Kommentare eingefügt. So kann das Ganze als Sample zum Unterscheiden von ENTER und RETURN dienen:

    VB.NET-Quellcode

    1. Const WM_KEYDOWN As Integer = &H100
    2. Const KF_EXTENDED = &H1000000
    3. Private Ex As Boolean
    4. Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message,
    5. ByVal keyData As System.Windows.Forms.Keys) As Boolean
    6. 'Distinguish between 'ENTER / RETURN:
    7. 'Event routines like KeyDown present Keys.Return (13 = 0x0D) both on ENTER and RETURN
    8. 'ProcessCmdKey override is used to distinguish between the two keys.
    9. '1. Catch ENTER and RETURN:
    10. ' msg.Msg WM_KEYDOWN (256 = 0x0100) (key down)
    11. ' msg.WParam (13 = 0x000d) (Keys.Return)
    12. '2. Distinguish ENTER and RETURN:
    13. ' msg.LParam contains 18.612.225 = 0x011c 0001 for ENTER
    14. ' msg.LParam contains 1.835.009 = 0x001c 0001 for RETURN
    15. '
    16. 'The two keys are just different on Bit 24
    17. 'KF_EXTENDED (0x0100 0000) is used to test Bit 24
    18. If msg.Msg = WM_KEYDOWN AndAlso msg.WParam.ToInt32 = Keys.Return Then 'Catch ENTER and RETURN
    19. Ex = ((msg.LParam.ToInt32() And KF_EXTENDED) = KF_EXTENDED) 'Test Bit 24
    20. If Ex Then
    21. Debug.Print("ProcessCmdKey --> ENTER key was depressed")
    22. 'Process ENTER key ...
    23. Else
    24. Debug.Print("ProcessCmdKey --> RETURN key was depressed")
    25. 'Process RETURN key ...
    26. End If
    27. Return True 'Terminate keystroke processing
    28. End If
    29. Return MyBase.ProcessCmdKey(msg, keyData) 'All other keys are left as is
    30. End Function


    Ich hab noch ein paar Probleme mit der dgv aber die stelle ich dann besser in einen eigenen Thread !

    Nochmals vielen Dank an die Ratgeber und erst mal Daumen hoch !

    LG
    Peter