ISPF Editor unter VB

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

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

    ISPF Editor unter VB

    Hi,

    wie einige vielleicht wissen, bin ich in der Welt der Großrechner unterwegs ... dort heißt das Betriebssystem z/OS und das Dialogsystem TSO/E ISPF.

    Einen ISPF Editor haben die auch ... und der hat einige ganz spezielle Eigenschaften. Es gib eine "Prefix Area" und eine Command Line mit denen man, manche Aufgaben sehr elegant lösen kann. Das würde ich manchmal auch auf dem PC gern nutzen wollen. Und deshalb versuche ich das Dingens unter VB nachzubauen, jedenfalls die Funktionen, die ich nutzen möchte.

    Basis ist eine Datagrid view, mit zwei Spalten: der Prefix Area (da stehen jetzt einfach die Zeilennummern drin) und der Text Zeile.

    Wenn ich die Anwendung starte wird die DGV geladen und die Selektion aufgehoben (s. EDIT 1)

    Wenn ich nun eine Zeile verändern möchte, dann klicke ich diese an. Diese Zelle wird braun eingefärbt (so hab ich das eingestellt). (s. EDIT 2)

    Wenn ich diese Zelle noch einmal anklicke, dann wird sie ausgewählt und blau einfärbt (so hab ich das auch eingestellt). (s. EDIT 3)

    Und wenn man jetzt noch einmal klickt, dann wird die Zelle editiert, d.h. die Färbung verschwindet und der Text Cursor wird in die Zelle plaziert. (s. EDIT 4)

    Jetzt kann ich die Daten der Zelle verändern.

    Aber so kann ich nicht arbeiten ! Ich muss jede Zelle DREI MAL anklicken bis ich meinen Textcursor erhalte !

    Ich hätte gerne, dass die Zelle SOFORT in den Edit Modus geht sobald ich sie mit dem Cursor anklicke bzw, mit den Tasten "Arrow Down" oder "Arrow Up" ansteuere.

    Mit anderen Worten ich muss in den Ereignisprozeduren

    VB.NET-Quellcode

    1. Private Sub dgvEdit_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles dgvEdit.CellClick


    und

    VB.NET-Quellcode

    1. Private Sub dgvEdit_CellEnter(sender As Object, e As DataGridViewCellEventArgs) Handles dgvEdit.CellEnter


    geignete Massnahmen ergreifen ... Nur wie mache ich das ? Wie kriege ich die Zelle dazu SOFORT in den Edit Modus zu schalten !

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

    Vielleicht ist eine DGV ja auch nicht das probate Mittel ... alternative Ideen sind willkommen.

    LG
    Peter
    Bilder
    • EDIT 1.jpg

      54,05 kB, 924×590, 134 mal angesehen
    • EDIT 2.jpg

      55,8 kB, 924×590, 128 mal angesehen
    • EDIT 3.jpg

      54,96 kB, 924×590, 117 mal angesehen
    • EDIT 4.jpg

      54,65 kB, 924×590, 106 mal angesehen
    @Peter329 Ist das "Denen ihr" Editor oder ist das "Dein" Editor?
    Falls "Denen ihr": Warum nimmst Du nicht einfach ne RichTextBox, da bist Du immer im Edit-Modus.
    Falls Du die Zeilen einzeln "scharf" machen musst:
    Mach Dir ein UserControl mit folgenden Eigenschaften:
    Ein Zustand zur Anzeige,
    ein Zustand zum Editieren.
    Umschaltung über ReadOnly = False | True
    Jede Zeile Deines Textes wäre dann ein UserControl, mit Properties Last und Next kannst Du hoch und runter navigieren, und alle werden in nem FlowLayoutPanel gelistet.
    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 ist mein Control. Im z/OS ISPF gibt es keine Objektorientierung ... da ist alles prozedural.

    Ja, ich muss die Zeilen einzeln "scharf" machen ... weil es "Prefix Commands" gibt, die dann genau auf eine Zeile wirken.

    Ich hab jetzt etwas entdeckt:

    VB.NET-Quellcode

    1. Private Sub dgvEdit_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles dgvEdit.CellClick,
    2. dgvEdit.CellEnter
    3. If e.ColumnIndex = 1 Then 'Text column clicked
    4. dgvEdit.BeginEdit(True)
    5. End If
    6. End Sub


    Damit kann ich schon mal die "braune" Phase ausblenden ... ich komme jetzt mit MouseClick, bzw der Arrow Taste sofort in die blaue Phase.

    Aber dann brauche ich immer noch einen MouseClick um in die Phase 4 zu gelangen !

    Das ist zwar schon besser aber immer noch nicht das was ich mir vorstelle ! Wie kann ich denn diesen zweiten Click vermeiden ? Also die Zelle "aktivieren" und den TextCursor an den Anfang der Daten stellen.

    LG
    Peter
    @Peter329 Wie bildest Du denn dieses OS-Zeugs ab? Da müsstest Du ja die Objektorientierung Deines Controls aufweichen. :/
    Du könntest eine randlose Form anzeigen, in der in einer TextBox die zu editierende Zeile angezeigt 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!
    Also vergessen wir mal die z/OS Geschichte.

    Woran ich jetzt hänge ist folgendes:

    Wenn ich eine Zelle mit MouseClick oder Arrow anspringe, dann führe ich das folgende Coding aus:

    VB.NET-Quellcode

    1. Private Sub dgvEdit_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles dgvEdit.CellClick,
    2. dgvEdit.CellEnter
    3. If e.ColumnIndex = 1 Then 'Text column clicked
    4. dgvEdit.BeginEdit(True)
    5. End If
    6. End Sub


    Dies liefert Bild EDIT 3. Die Zelle wird blau unterlegt und es gibt keinen Textcursor. Das ist nicht was ich haben will.

    Wenn ich jetzt die Zelle anklicke, dann erhalte ich Bild EDIT 4. Die Markierung verschwindet, und der TextCursor wird eingeblendet. Das ist es was ich haben will.

    Und genau diesen Click will ich einsparen.

    Die Frage ist also, wie ich den Text Cursor PROGRAMMATISCH in die aktuelle Zelle kriege, etwa an den Anfang des Textes ! Oder noch besser an die Position auf die ich beim ersten Click gezeigt habe.

    So was habe ich bisher versucht:

    VB.NET-Quellcode

    1. If e.ColumnIndex = 1 Then 'Text column clicked
    2. dgvEdit.BeginEdit(True)
    3. 'dgvEdit.Item("itmEditText", e.RowIndex).Selected = True 'causes a tight loop
    4. dgvEdit.CurrentCell = dgvEdit.Item("itmEditText", e.RowIndex) 'does not help
    5. 'dgvEdit.Item("itmEditText", e.RowIndex).Style ??? 'keine Ahnung ob da was zu machen ist
    6. End If

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

    @Peter329 Hängt hinter dem DGV eine DataTable?
    Dies tut es bei mir:

    VB.NET-Quellcode

    1. Private table As DataTable
    2. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    3. table = New DataTable("bla")
    4. table.Columns.Add("Nummer", GetType(String))
    5. table.Columns.Add("Text", GetType(String))
    6. DataGridView1.DataSource = table
    7. End Sub
    8. Private Sub DataGridView1_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellClick
    9. DataGridView1.BeginEdit(True)
    10. End Sub

    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!
    Bisher habe ich noch keine DataTable dahinter gehängt.

    Aber wenn das so bei dir funktioniert, dann sollte ich das wohl auch ausprobieren. Dauert aber ein Weilchen, weil ich mich jetzt erst mal ausklinken muss ...

    Danke für deine Ratschläge .... ich melde mich morgen wieder.

    LG
    Peter
    in diesem Zusammenhang ist sicher nützlich, zu wissen, dass wo man reinschreibt im DGV - das ist eiglich garnet mehr das DGV.
    Sondern wenn das DGV in den Editmodus geht, erzeugt es genau über der Zelle ein Popup einer Textbox drauf - das sog. EditingControl.

    Ist bisserl schwierig, dessen habhaft zu werden, DGV_EditingControlShowing mag dein Froind sein.
    Jdfs. wenn mans erwischt, kann mans auch manipulieren (mit bischen Umstand) wie eine normale Textbox (bei TextboxColumns).
    So, da bin ich wieder.

    Ich habe jetzt den Ratschlag von RFG befolgt und die Daten über eine DataTable an die DGV gebunden:

    VB.NET-Quellcode

    1. 'Create data table and define columns
    2. Dim dt As New DataTable("myDataTable")
    3. dt.Columns.Add("Number", GetType(String))
    4. dt.Columns.Add("Text", GetType(String))
    5. 'Fill data table
    6. dt.Rows.Add(New Object() {"******", TopRow})
    7. dt.Rows.Add(New Object() {"000001", "//SYSPRINT DD SYSOUT=*"})
    8. dt.Rows.Add(New Object() {"000001", "//SYSPRINT DD SYSOUT=*"})
    9. dt.Rows.Add(New Object() {"000002", "//SYSIN DD *"})
    10. dt.Rows.Add(New Object() {"000003", " REPRO IFILE(FILEA) ODS(TESTUSR1.TEST.DATA)"})
    11. dt.Rows.Add(New Object() {"000004", " LISTCAT ENT(TESTUSR1.TEST.DATA)"})
    12. dt.Rows.Add(New Object() {"000005", "/*"})
    13. dt.Rows.Add(New Object() {"******", BottomRow})
    14. 'Bind datasource to datagridview
    15. dgvEdit.DataSource = dt
    16. 'Remove default selection from datagridview
    17. dgvEdit.ClearSelection()


    Über die Events CellClick und CellEnter schalte ich die zweite Spalte ("Text") in den EditMode.

    Das Ergebnis ist aber leider bei mir unverändert. Zunächst wird die Zelle blau hinterlegt angezeigt. Und erst ein Click entfernt die Farbe und blendet den TextCursor ein.

    Außerdem kriege ich die Formatierung der zweiten Zelle nicht hin. Da die Spalten jetzt nicht mehr im Designer definiert werden, erhalten sie eine Default Länge die zu kurz ist. Ich hab das wie folgt zu lösen versucht, aber ich erhalte einen Fehler:

    VB.NET-Quellcode

    1. 'Assign datagridview properties (cell width)
    2. Dim tabStyle As New DataGridTableStyle()
    3. tabStyle.MappingName = "myDataTable"
    4. Dim Col As New DataGridTextBoxColumn()
    5. Col.MappingName = "Text"
    6. Col.Width = 180
    7. tabStyle.GridColumnStyles.Add(Col)
    8. 'dgvEdit.TableStyles.Clear() '<-- TableStyles ist kein Member von DataGridView
    9. 'dgvEdit.TableStyles.Add(tabStyle)


    Der Hinweis von EDR ist natürlich sehr interessant. Nur hab ich leider nicht die geringste Ahnung wie ich das umsetzen soll.

    LG
    Peter

    Peter329 schrieb:

    Das Ergebnis ist aber leider bei mir unverändert.
    Jetzt weiß ich, was Du meinst. :thumbsup:
    Sieh Dir mal den Parameter (hier True) an:

    VB.NET-Quellcode

    1. DataGridView1.BeginEdit(True)
    Zur Einrichtung der Spaltenbreite sieh Dir mal diese Prozedur an:
    Spoiler anzeigen

    C#-Quellcode

    1. /// <summary>
    2. /// Spaltenbreite des DGV so einrichten,
    3. /// dass alle Spalten optimal angezeigt werden
    4. /// </summary>
    5. /// <param name="dgv">das zu behandelnde DataGridView</param>
    6. private static void DgvAutoColumnSize(DataGridView dgv)
    7. {
    8. dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
    9. int x = 0;
    10. foreach (DataGridViewColumn col in dgv.Columns)
    11. {
    12. x += col.Width;
    13. //Console.Out.WriteLine("{0}\t{1}", col.Width, col.MinimumWidth);
    14. }
    15. if (x < dgv.Width)
    16. {
    17. // getestet, 1. Spalte breiter
    18. foreach (DataGridViewColumn col in dgv.Columns)
    19. {
    20. col.MinimumWidth = col.Width;
    21. }
    22. dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
    23. }
    24. else
    25. {
    26. //dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
    27. dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
    28. }
    29. }
    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:

    Jetzt weiß ich, was Du meinst. :thumbsup:


    Jau ... ich bin ja immer froh, wenn ich mein Anliegen verständlich machen kann. So klappt das jetzt mit dem Ausschalten der Markierung:

    VB.NET-Quellcode

    1. dgvEdit.BeginEdit(selectAll:=False)


    Und auch das Einstellen der Spaltenattribute funzt:

    VB.NET-Quellcode

    1. For Each EditCol As DataGridViewColumn In dgvEdit.Columns
    2. Dim myFont As New Font("Courier New", 12, FontStyle.Regular)
    3. EditCol.DefaultCellStyle.Font = myFont
    4. If EditCol.Name = "Number" Then EditCol.Width = 70
    5. If EditCol.Name = "Text" Then EditCol.Width = 810
    6. Next


    Das sieht jetzt schon sehr viel besser aus. Allerdings bin ich mit dem Verhalten der dgv immer noch nicht ganz happy:

    1. Wenn ich in der dgv die Zelle "Text" anklicke, dann springt der Textcursor immer an das ENDE der TextZeile, ganz egal an welcher Position ich den Text angeklickt habe. Erst durch einen ZWEITEN Click kann ich den Textcursor positionieren. Mir wäre es lieber, der Textcursor würde gleich an genau die Stelle springen, die ich in der Zelle angeklickt habe!

    2. Das gleich passiert wenn ich die Text Zelle mit der PfeilTaste anspringe (Arrow up, Arrow down). Auch hier wird der TextCursor ans Ende des Textes in der Zelle gestellt. MIr wäre es lieber, wenn der TextCursor nicht ans Ende springt, sondern, seine x-Koordinate beibehält, wenn ich etwa die Arrow down Taste bediene. Die Schrift ist nicht-proportional, das sollte doch eigentlich machbar sein.

    LG
    Peter
    mhh, sieht so aus als gäbe es für mein Problem keine Lösung.

    Na gut, man sollte eben Controls möglichst so nutzen wie sie "gebaut" sind - sonst handelt man sich nur Probleme ein.

    Auf dem z/OS Großrechner verwendet man (originär) Block-orientierte Bildschirme, die BYTES und nicht Pixel abbilden ... die Steuerung des Cursors übernimmt die Hardware ... und dies wird auf dem PC durch die Emulationssoftware umgesetzt. Das kann man halt nicht so ohne weiteres in die .NET Welt abbilden. Und deshalb werde ich mit bestimmten Verhaltensweisen der DGV wohl einfach "leben" müssen.

    Mein ISPF Editor auf dem PC läuft inzwischen recht annehmbar. Trotzdem habe ich nach wie vor einige (legitime) Anliegen, wie man den Text Cursor einer DGV steuern kann. Aber dafür mache ich dann besser einen neuen Thread auf, um die Dinge sauber zu trennen.

    Also, erst mal vielen Dank an die Ratgeber ...

    LG
    Peter
    Vielleicht dieser Weg, um das Caret in einer DataGridViewTextboxEditingCell zu setzen:

    VB.NET-Quellcode

    1. Private Sub MyDataTableDataGridView_CellEnter(sender As Object, e As DataGridViewCellEventArgs) Handles MyDataTableDataGridView.CellEnter
    2. If Me.MyDataTableDataGridView.CurrentCell.EditType = GetType(DataGridViewTextBoxEditingControl) Then
    3. MyDataTableDataGridView.BeginEdit(False)
    4. With DirectCast(MyDataTableDataGridView.EditingControl, TextBox)
    5. .SelectionStart = .Text.Length
    6. End With
    7. End If
    8. End Sub
    Wow, Klasse ! Das ist ja genau die Sache, die ich nach der Bemerkung von EDR gesucht hatte: die Möglichkeit auf die TextBox der Editing Control zuzugreifen.

    Die Definition klappt hervorragend ... jetzt will ich mal sehen, was ich mit dem Dingens alles anstellen kann!

    Danke, du hast meinen Tag gerettet! :)

    LG
    Peter