Datagrid View EDIT Mode kontrollieren

  • VB.NET

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

    Datagrid View EDIT Mode kontrollieren

    Hi,

    in einer Datagrid View gibt es den "Edit Mode" der Zelle.

    Wenn man die Zelle anklickt, wird eine Textbox über die Zelle gelegt und der Inhalt der Zelle wird selektiert.

    Aus verschiedenen Gründen möchte ich aber den Text deselektieren und den Text Cursor an das Ende des Textes stellen.

    (klar - ich kann einfach auf das Ende des Textstrings klicken, dann hab ich das auch - aber aus Gründen der "usability" würde ich diesen Click gern vermeiden - weil es das ist, was die Leute in 9 von 10 Fällen machen werden. :) )

    Ich brauche also eine Anweisung der folgenden Gestalt:

    VB.NET-Quellcode

    1. Dim myTextbox As TextBox = DirectCast(sender, TextBox)
    2. If myTextbox.Text.Length > 0 Then myTextbox.Select(myTextbox.Text.Length - 1, 0)


    Aber wo bringe ich diese Anweisung unter ?

    Im EditingControlShowing Event ist das nicht möglich ... da gibt es die Textbox noch nicht.

    Ich brauche also ein Event, das nach dem Erzeugen der Textbox feuert. Die Liste der verfügbaren Events hab ich durchforstet. Aber irgendwie finde ich da nix Passendes.

    Ich hoffe, ich habe mein Anliegen verständlich machen können.

    LG
    Peter
    Für alle Leser: Wir befinden uns in einem DGV.

    Peter329 schrieb:

    Im EditingControlShowing Event ist das nicht möglich ... da gibt es die Textbox noch nicht.
    Doch. Ist in e versteckt. Aber das weißt Du ja auch, Du nutzt es ja später.
    Das geht mit meinem Lieblings-workaround:

    VB.NET-Quellcode

    1. Private Async Sub DataGridView1_EditingControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
    2. Await Threading.Tasks.Task.Delay(1)
    3. Dim DgvTextBox = DirectCast(e.Control, TextBox)
    4. DgvTextBox.SelectionStart = DgvTextBox.Text.Length
    5. End Sub
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    VaporiZed schrieb:

    Doch. Ist in e versteckt. Aber das weißt Du ja auch, Du nutzt es ja später.


    Huch ? Tue ich das ? :)

    VaporiZed schrieb:


    Das geht mit meinem Lieblings-workaround:

    VB.NET-Quellcode

    1. Private Async Sub DataGridView1_EditingControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
    2. Await Threading.Tasks.Task.Delay(1)
    3. Dim DgvTextBox = DirectCast(e.Control, TextBox)
    4. DgvTextBox.SelectionStart = DgvTextBox.Text.Length
    5. End Sub


    Mhh ... also das funktioniert bei mir (nachdem ich das mit dem "Async" aufgenommen habe).

    Kannst du mir erklären WIE das funktioniert ?

    LG
    Peter

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

    @Peter329 Das Programm wartet ohne die GUI zu blockieren 1 Millisekunde in einem anderen Thread.
    Diese Zeit bekommt die nicht blockierte GUI zum Updaten..
    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, hab ich verstanden, danke ihr beiden.

    Nachdem sich für mein Edit Problem so unerwartet schnell eine Lösung gefunden hat, habe ich Hoffnung, dass auch mein zweites Problem eine Antwort findet.

    Im Anhang seht ihr mein "Vokablheft" im Edit Mode der ersten Spalte (dark blue ist die Edit unselected color).

    Wenn ich jetzt die Tab Taste drücke wird der Edit Mode geschlossen. Das ist blöde. Denn den Edit Mode hätte ich auch einfach durch einen Klick schließen können !

    Tab sollte in das NÄCHSTE Eingabefeld in den Edit Mode wechseln. Denn das ist es, was "normale" Menschen unter "TAB" erwarten würden.

    Oh jemineh ! Ich weiß, dass die Tab Taste von Windows abgefangen wird ... ob das jetzt machbar ist, da habe ich große Zweifel.

    Na ja, die Hoffnung stirbt zuletzt. Vielleicht habt ihr ja eine briliante Idee, wie ich das realisieren kann. :)

    Klar, mit zwei Klicks auf die Zelle unter der Spalte "English" habe ich das gewünschte Ergebnis auch ... aber ihr wisst ja schon ... usability ... wäre halt nett, wenn man diese Clicks dem User ersparen könnte ... Zumal die Sache mit dem TAB an anderer Stelle genauso gehandhabt wird.

    LG
    Peter
    Bilder
    • s 2020-06-13 13-36-067.jpg

      15,61 kB, 490×153, 78 mal angesehen
    • s 2020-06-13 13-50-082.jpg

      15,15 kB, 495×152, 67 mal angesehen

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

    Peter329 schrieb:

    Huch ? Tue ich das ?

    In Deinem anderen Thread von gestern wandelst Du doch e.Control ebenfalls um. Zwar nicht in eine TextBox, aber machst aus e.Control per DirectCast das CE, welches Du brauchst.

    Ich benutze diesen workaround immer wieder. Mal updatet sich ein DGV nicht, bevor ich direkt eine Änderung der Anzeige mache, mal will ne PicBox nicht so richtig. Bedenke aber, dass es genau das bleibt: ein workaround. Andere würden es einen Hack nennen. Denn es schwebt immer der Geruch von Trick oder Unsauberkeit mit. Allerdings werde ich ihn solange verwenden, bis ich eine bessere Lösung gefunden habe.

    ##########

    @Peter329:
    Die Tab-Taste macht doch genau das, was Du von ihr erwartest. Ergänzen kannst Du das durch

    VB.NET-Quellcode

    1. Private Sub DataGridView1_CellEnter(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellEnter
    2. DataGridView1.BeginEdit(False)
    3. End Sub
    Dann geht beim Zellselektieren die gleich in den EditMode über, ohne deren Inhalt vollumfänglich zu markieren.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

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

    Peter329 schrieb:

    Ich weiß, dass die Tab Taste von Windows abgefangen wird ...
    Ich hab mal eben fix eine neue Form mit nem DGV mit 4 Spalten erstellt.
    Wenn ich abwechselnd {Tab} und "lkj" eingebe, werden 4 Spalten in beliebig viele Zeilen befüllt.
    So, wie das

    Peter329 schrieb:

    "normale" Menschen unter "TAB" erwarten würden.
    Wenn das bei Dir nicht geht, hast Du das selbst verbaut.
    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!
    Das mit dem

    DataGridView1.BeginEdit(False)

    hab ich ausprobiert.

    Tatsächlich klappt dann die Tab-Taste ... die springt von Eingabefeld zu Eingabefeld ... genauso wie mir das gefällt ! Und insbesondere ist dann auch die Umgehung mit "Wait" nicht mehr erforderlich.

    Aber ...

    ... damit handele ich mir eine ganze Reihe von Widrigkeiten ein:

    1. Nach dem Aufbau der dgv geht das Dingens SOFORT in den Edit mode. (Das könnte man mit einem EndEdit vermutlich noch leicht beheben).

    2. Wenn ich eine andere Zelle anklicke, wird die sofort im Edit Mode geöffnet - bisher wurde durch so einen Klick der aktuelle Edit Mode beendet und die angeklickte ZEILE selektiert. Und so sollte das auch sein.

    3. Wenn die Zelle am Ende der Zeile liegt, dann bring mich TAB in die NÄCHSTE Zeile ... - besser wäre es, wenn die Reise in die erste Zelle der GLEICHEN Zeile gehen würde.

    4. Mit der rechten Maustaste habe ich bisher die aktuelle Selection abgewählt (und ggfs. den Edit Mode beendet). Auch das ist eine Funktionalität, die erhalten bleiben sollte. Weil sich anderer Controls in genau der gleichen Weise verhalten.

    Also alles in allem habe ich mir mt BeginEdit(False) mehr Probleme eingehandelt als ich gewonnen habe !

    BeginEdit(False) kann ich in dieser Form leider nicht verwewnden.

    Any other bright ideas ?

    LG
    Peter

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

    @Peter329 Dann mach Dir ein (Enum-)Flag, das beschreibt, in welchem Modus die delektierte Zelle erscheinen soll, das definierst Du anhand Deines Kontexts und setzt Du dann um, wenn eine neue Zelle fokussiert wird.
    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 ... gute Idee ...

    Ich hab das mal wie folgt umgesetzt ...

    VB.NET-Quellcode

    1. Private Sub dgvDictionary_SelectionChanged(sender As Object, e As EventArgs) Handles dgvDictionary.SelectionChanged
    2. UpdateCount()
    3. Try
    4. dgvDictionary.EndEdit()
    5. Catch ex As Exception
    6. End Try
    7. End Sub


    Wenn ich eine neue Zeile anklilcke ... dann wird zwar der Edit Mode aktiviert ... aber gleich wieder von meiner Event Routine beendet ... das flacker zwar kurz .... aber damit könnte ich noch leben. Obwohl ich nicht so ganz euphorisch über diese Lösung bin. :)

    Allerding wenn man sich anfangs noch nicht im Edit Mode befunden hat, dann gibt es eine Exception:

    Ausnahme ausgelöst: "System.NullReferenceException" in Dictionary.exe
    Object reference not set to an instance of an object.

    Klar kann ich das mit Try - Catch abfackeln ... aber so richtig "koscher" sieht mir das nicht aus ... das müsste man halt irgendwie vorher abfragen ... nur, wie mache ich das ?

    LG
    Peter

    Peter329 schrieb:

    nur, wie mache ich das ?
    Das solltest Du aber "einfach so" rausbekommen, wenn Du das Programm in der Entwicklungsumgebung laufen lässt.
    Ieine Variable / Member / Property ist da Nothing, und das kannst Du mit nem If abfangen.
    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!
    Na ja ... einfach so... das Dingens hat vielleicht drei Dutzend Eigenschaften ... ich hab mal zwei Kandidaten ausprobiert:

    VB.NET-Quellcode

    1. Try
    2. Debug.Print("EditMode=" & dgvDictionary.IsCurrentCellInEditMode.ToString)
    3. Debug.Print("EditingPanel=" & dgvDictionary.EditingPanel.ToString)
    4. dgvDictionary.EndEdit()
    5. Catch ex As Exception
    6. Debug.Print(ex.Message)
    7. End Try


    EditMode=True
    EditingPanel=System.Windows.Forms.Panel, BorderStyle: System.Windows.Forms.BorderStyle.None
    Ausnahme ausgelöst: "System.NullReferenceException" in Dictionary.exe

    Also die beiden sind es schon mal nicht ! :)

    Ein HInweis ... ehe ich heute Trubsal versinke ... ?

    LG
    Peter
    @Peter329 Wie genau hast Du denn die Stelle eingegrenzt?
    Setz nen Haltepunkt drauf, rechte Maustaste, Überwachung hinzufügen, und dann unten im "Überwachen"-Fenster rumklickern.
    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!
    Ohne Try-Catch. Dann bekommt man immer noch die meisten Infos.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    ok ... ich hab "try cast" rausgenommen und die Sache im Debugger verfolgt ... Der Fehler liegt ganz woanders ... im EndEdit Event habe ich auf eine SortColumn zugegriffen, die noch nicht gesetzt war, daher die NullReference ... mit der EditTextbox hat das also gar nix zu tun.

    Jetzt läuft das. Aber ... das Verhalten gefällt mir ganz und gar nicht ...

    Jetzt werden zwar die dgv Zeilen wieder ordentlich also ohne Edit Mode selektiert ... aber wenn die dgv den Focus hat und ich jetzt ein Zeichen eingebe, dann wird automatisch die erste Zelle der Zeile im Edit Mode geöffnet ... und der Inhalt der Zelle wird mit dem eingegebenen Zeichen überschrieben.

    Bums! Das ist natürlich saublöde.

    Man kann das zwar durch Drücken der ESCAPE Taste wieder rückgängig machen ... aber so ein Verhalten ist natürlich prohibitiv. Schade, die Idee klang so wunderbar !

    Ich fürchte, ich werde die Idee mit BeginEdit(False) und der TAB Taste aufgeben müssen. Na ja, man kann eben nicht alles im Leben haben ...

    Es sei denn ihr habt doch noch eine geniale Idee, wie ich ohne "BeginEdit(False)" mit der Tab Taste die editierte Zelle wechseln kann.

    LG
    Peter
    @Peter329 Mir kommt da ne gaaaaanz andere Idee:
    Um wie viele Zellen (Zeilen/Spalten) handelt es sich?
    Du könntest ja im Prinzip das DGV über ein TableLayoutPanel nachbilden, in dessen Zellen sich TextBoxen befinden.
    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:

    @Peter329 Mir kommt da ne gaaaaanz andere Idee


    Erst mal Danke für deine Idee. Ich bin ja sehr offen, für neue Ansätze - aber jetzt bleibe ich erst mal bei meinem Verfahren. Wer weiß welche Probleme ich mir bei so einer komplexen Kiste sonst einhandeln würde. Zumal meine dgv tatsächlich sehr viel mehr als nur zwei Spalten enthält. :)

    Ich hab das Problem jetzt gelöst. Für alle, die es möglicherweise interessiert:

    Ich hab zu Beginn jeder Ereignis Prozedur ein Debug.Print eingebaut ... um zu sehen, wann und in welcher Reihenfolge die Events feuern und welche Daten mir dann zur Verfügung stehen. Denn immerhin sind hier rund ein Dutzend Event-Routinen beteiligt !

    Wirklich tricky ist eigentlich nur die Sache mit dem unmittelbaren Eintritt in den Edit-Mode, wenn man irgend eine Text-Taste drückt. Denn wenn man das macht, dann wird automatisch der Edit-Mode ausgelöst und die Daten in der Zelle werden durch das gedrückte Zeichen überschrieben. Das ist für meine Anwendung nicht akzeptabel und deshalb muss ich das im KeyDown Event abfangen.

    Aber natürlich, muss ich im Edit Mode Eingaben zulassen. Deshalb setze ich im Preview_Keydown Event einen Schalter. Denn dieses Event feuert VOR dem BeginEdit: Wenn die Eingabe im Edit Mode erfolgt ist, dann wird sie akzeptiert. Wenn der Edit Mode aber durch eine Text-Taste außerhalb des Edit Mode ausgelöst wurde, dann beende ich den Edit Mode gleich wieder. Das geht leider nicht im KeyPreview Event (da gibt es kein e.Handled), sondern erst im KeyDown Event ... und deshalb braucht man einen Schalter.

    Nicht ganz so einfach .... aber vielleicht hilfreich für Leute, die ähnliche Probleme an der Backe haben.

    Mein "Dictionary" läuft jetzt prima ... der BeginEdit selektiert keine Daten, sondern stellt das Caret ans Ende der vorhandenen Daten in der Zelle, mit CTRL-Akzent kann ich im Edit Mode die Akzente "toggeln" ... die TAB Taste bringt mich im Edit Mode in die nächste Eingabe Zelle ... CTRL-C, X und V funktionieren im Edit Mode mit gewissen Sonderfunktionen ... und wenn sich die dgv nicht im Edit Mode befindet, dann verhält sie sich so, als wäre sie Read Only !

    Danke für eure Hilfe ... die Diskussion mit euch hat mir sehr weiter geholfen !

    LG
    Peter

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