RichTextbox Textfarbe ändern funktioniert nur beim letzten Eintrag

  • VB.NET
  • .NET 5–6

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von VaporiZed.

    RichTextbox Textfarbe ändern funktioniert nur beim letzten Eintrag

    Hallo Leute,
    ich habe einen Text in einer RichTextbox:

    "Hans Dampf der Raucher, Dagobert Duck der Millionär, Elon Musk der Milliardär und Rudi Rüssel sitzen in einem Boot."

    dieser Text soll nach erfolgreich durchgeführten Code so aussehen:
    "<person id=1>Hans Dampf</person> der Raucher, <person id=2>Dagobert Duck</person> der Millionär, <person id=3>Elon Musk</person> der Milliardär und <person id=4>Rudi Rüssel</person> sitzen in einem Boot."

    Ich gleiche die Namen aus einem Datagridview mit dem Inhalt der Richtextbox ab, die Einträge werden geändert und die Änderungen sollen rot dargestellt werden.
    Die Änderung der Namen funktioniert ohne Probleme wie folgt:

    VB.NET-Quellcode

    1. Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
    2. 'Bearbeite Richtextbox1 (Ereigniss Text)
    3. '1. nach Personen durchsuchen
    4. For i As Integer = 0 To Me.DataGridView2.Rows.Count - 2
    5. 'Definiere Variablen zu Personen aus DGV2
    6. Dim personID As String = Me.DataGridView2.Item(0, i).Value.ToString 'PersonenID auslesen
    7. Dim nachname As String = Me.DataGridView2.Item(1, i).Value.ToString 'Nachname auslesen
    8. Dim vorname As String = Me.DataGridView2.Item(2, i).Value.ToString ' Vorname auslesen
    9. Dim name As String = vorname & " " & nachname 'Erstelle variable Name (Vorname und Nachname mit eine Leerzeichen)
    10. 'Prüfe, ob RichTextbox1 in seinem Text den Text der Varibale Name enthält
    11. If RichTextBox1.Text.Contains(name) Then
    12. 'Wenn Ja...
    13. 'Definiere den neuen Eintrag <person id=xxx>Vorname Name</person>
    14. Dim neueeintrag = "<person id=" & personID & ">" & name & "</person>"
    15. 'Ändern der Einträge in der RichTextbox1
    16. Me.RichTextBox1.Text = Me.RichTextBox1.Text.Replace(name, neueeintrag) 'Ersetze den geunfen Namen durch den neuen Eintrag
    17. Dim eintrag = RichTextBox1.Text.IndexOf(neueeintrag) 'Index soll dort sein, wo neuer Eintrag entstanden ist
    18. Dim laenge = neueeintrag.Length 'Länge des Strings auslesen
    19. RichTextBox1.Select(eintrag, laenge) 'Markiere den neuen Eintrag
    20. RichTextBox1.SelectionColor = Color.Red 'die Textfarbe des markierten Eintrages in Rot ändern
    21. End If
    22. Next
    23. End Sub


    Jetzt passiert aber folgendes. Es wird immer nur der letzte Eintrag rot markiert.
    "<person id=1>Hans Dampf</person> der Raucher, <person id=2>Dagobert Duck</person> der Millionär, <person id=3>Elon Musk</person> der Milliardär und <person id=4>Rudi Rüssel</person> sitzen in einem Boot."

    Wenn ich jetzt aus z.b. Rudi Rüssel raus lasse, dann wird Elon Musk rot markiert.
    "<person id=1>Hans Dampf</person> der Raucher, <person id=2>Dagobert Duck</person> der Millionär, <person id=3>Elon Musk</person> der Milliardär sitzen in einem Boot."

    Bei allen anderen wird zwar der Text in den <person.... Code umgeschrieben, aber die Farbe des Textes ist schwarz.
    Es scheint so, als würde bei jedem Durchlauf der bereits rote Text wieder schwarz werden und nur der letzte gefunde Eintrag wird rot markiert.

    Kann mir jemand helfen, wie ich den roten Text bei allen Markierungen behalten kann.
    Ich habe nicht mal einen Ansatz, wonach ich suchen soll um dieses Problem zu lösen.

    die Farbe Rot ist der Moderation vorbehalten und entsprechende Passagen wurden durch Inline-CodeTags ersetzt ~VaporiZed

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

    Hey,

    das Programm führt das immer aus, bei jedem Vorkommen, bzw. in jeder Zeile wird es einmal beim ersten vorkommen gemacht. 8o
    Ja wirklich.
    Aber du entfernst es selbst wieder.
    Wie? Indem du den Text der RTB holst änderst und dann den geänderten Text der RTB zuweist. Die RTB hat eine weitere Property RichTextBox.Rtf, das ist dann der RichText mit Daten über Farbe etc... Weist du einen normalen Text zu, ist alles weg. Also hohle den Rtf und dann weist du der Rtf Property das geändert wieder zu. Dann sollte es zumindest bei jedem ersten Vorkommen pro Zeile klappen.
    Vollzitat des direkten Vorposts an dieser Stelle entfernt ~VaporiZed

    Ich versthe was du meinst:
    Indem ich mit

    VB.NET-Quellcode

    1. Me.RichTextBox1.Text = Me.RichTextBox1.Text.Replace(name, neueeintrag)

    den Text eigentlich erst kopieren, denn verändere und wieder einfüge, übernimmt er die Formatierungen nicht.

    Ich habe es jetzt so versucht:

    VB.NET-Quellcode

    1. Dim textformat = Me.RichTextBox1.Rtf
    2. Me.RichTextBox1.Text = Me.RichTextBox1.Text.Replace(name, neueeintrag) 'Ersetze den geunfen Namen durch den neuen Eintrag
    3. Me.RichTextBox1.Rtf = textformat
    4. Dim eintrag = RichTextBox1.Text.IndexOf(neueeintrag) 'Index soll dort sein, wo neuer Eintrag entstanden ist
    5. Dim laenge = neueeintrag.Length 'Länge des Strings auslesen
    6. RichTextBox1.Select(eintrag, laenge) 'Markiere den neuen Eintrag
    7. RichTextBox1.SelectionColor = Color.Red


    Dann bringt er mit aber bei

    VB.NET-Quellcode

    1. RichTextBox1.Select(eintrag, laenge)

    eine Fehlermeldung, weil dann (warum auch immer) der Wert "eintrag" immer als -1 angegeben wird.

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

    Dann korrigiere mal die Variablenname und dann dürfte klar sein, was das aktuelle Problem ist:

    VB.NET-Quellcode

    1. Dim ALTERTEXT = Me.RichTextBox1.Rtf '<-- !!!
    2. Me.RichTextBox1.Text = Me.RichTextBox1.Text.Replace(name, neueeintrag)
    3. Me.RichTextBox1.Rtf = ALTERTEXT '<-- !!!
    4. Dim eintrag = RichTextBox1.Text.IndexOf(neueeintrag)
    5. Dim laenge = neueeintrag.Length
    6. RichTextBox1.Select(eintrag, laenge)
    7. RichTextBox1.SelectionColor = Color.Red
    Durch die Namensänderung ändert sich natürlich nix im Ablauf, aber es sollte klar werden: Wenn Du den alten Text wieder zurück in die RTB packst, ist der neueeintrag nicht zu finden.

    ##########

    Wie wäre es denn, wenn Du in einer ersten Schleife die Textstellen ersetzt und in einer zweiten die Stellen rot markierst. Denn dann änderst Du den Textinhalt ja nicht mehr.
    btw: Was ist der Hintergrund dieser Übung? Was soll das werden, wenn's fertig ist?
    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.
    Ist zwar etwas kompliziert, viel Code und halt doppelte Arbeit es aber funktioniert mit dem doppelten Durchlauf:

    VB.NET-Quellcode

    1. Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
    2. 'Bearbeite Richtextbox1 (Ereigniss Text)
    3. '1. nach Personen durchsuchen und Text ersetzen
    4. For i As Integer = 0 To Me.DataGridView2.Rows.Count - 2
    5. 'Definiere Variablen zu Personen aus DGV2
    6. Dim personID As String = Me.DataGridView2.Item(0, i).Value.ToString 'PersonenID auslesen
    7. Dim nachname As String = Me.DataGridView2.Item(1, i).Value.ToString 'Nachname auslesen
    8. Dim vorname As String = Me.DataGridView2.Item(2, i).Value.ToString ' Vorname auslesen
    9. Dim name As String = vorname & " " & nachname 'Erstelle variable Name (Vorname und Nachname mit eine Leerzeichen)
    10. 'Prüfe, ob RichTextbox1 in seinem Text den Text der Varibale Name enthält
    11. If RichTextBox1.Text.Contains(name) Then
    12. 'Wenn Ja...
    13. 'Definiere den neuen Eintrag <person id=xxx>Vorname Name</person>
    14. Dim neueeintrag = "<person id=" & personID & ">" & name & "</person>"
    15. 'Ändern der Einträge in der RichTextbox1
    16. Me.RichTextBox1.Text = Me.RichTextBox1.Text.Replace(name, neueeintrag) 'Ersetze den geunfen Namen durch den neuen Eintrag
    17. End If
    18. Next
    19. ' 2. Nach Personen aus DGV2 suchen und Text einfärben
    20. For i As Integer = 0 To Me.DataGridView2.Rows.Count - 2
    21. 'Definiere Variablen zu Personen aus DGV2
    22. Dim personID As String = Me.DataGridView2.Item(0, i).Value.ToString 'PersonenID auslesen
    23. Dim nachname As String = Me.DataGridView2.Item(1, i).Value.ToString 'Nachname auslesen
    24. Dim vorname As String = Me.DataGridView2.Item(2, i).Value.ToString ' Vorname auslesen
    25. Dim name As String = vorname & " " & nachname 'Erstelle variable Name (Vorname und Nachname mit eine Leerzeichen)
    26. 'Prüfe, ob RichTextbox1 in seinem Text den Text der Varibale Name enthält
    27. If RichTextBox1.Text.Contains(name) Then
    28. 'Wenn Ja...
    29. 'Definiere den neuen Eintrag <person id=xxx>Vorname Name</person>
    30. Dim neueeintrag = "<person id=" & personID & ">" & name & "</person>"
    31. Dim eintrag = RichTextBox1.Text.IndexOf(neueeintrag) 'Index soll dort sein, wo neuer Eintrag entstanden ist
    32. Dim laenge = neueeintrag.Length 'Länge des Strings auslesen
    33. RichTextBox1.Select(eintrag, laenge) 'Markiere den neuen Eintrag
    34. RichTextBox1.SelectionColor = Color.Red 'die Textfarbe des markierten Eintrages in Rot ändern
    35. End If
    36. Next
    37. End Sub
    Codeduplikate wenn möglich immer auslagern:

    VB.NET-Quellcode

    1. Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. For i As Integer = 0 To Me.DataGridView2.Rows.Count - 2
    3. Dim Personendaten = HolePersonendatenAusDgvZeile(i)
    4. Me.RichTextBox1.Text = Me.RichTextBox1.Text.Replace(Personendaten.Name, GeneriereUndHoleNeuenEintragFür(Personendaten))
    5. Next
    6. For i As Integer = 0 To Me.DataGridView2.Rows.Count - 2
    7. Dim Personendaten = HolePersonendatenAusDgvZeile(i)
    8. Dim NeuerEintrag = GeneriereUndHoleNeuenEintragFür(Personendaten)
    9. RichTextBox1.Select(RichTextBox1.Text.IndexOf(NeuerEintrag), NeuerEintrag.Length)
    10. RichTextBox1.SelectionColor = Color.Red
    11. Next
    12. End Sub
    13. Private Function GeneriereUndHoleNeuenEintragFür(Personendaten As (PersonID As String, Name As String)) As String
    14. Return "<person id=" & Personendaten.PersonID & ">" & Personendaten.Name & "</person>"
    15. End Function
    16. Private Function HolePersonendatenAusDgvZeile(i As Integer) As (PersonID As String, Name As String)
    17. Dim personID As String = Me.DataGridView2.Item(0, i).Value.ToString
    18. Dim nachname As String = Me.DataGridView2.Item(1, i).Value.ToString
    19. Dim vorname As String = Me.DataGridView2.Item(2, i).Value.ToString
    20. Dim name As String = vorname & " " & nachname
    21. Return (personID, name)
    22. End Function


    Nächster Schritt wäre eine vernünftige Datenhaltung. Rohdaten in nem DGV sind fast immer ein Indiz für versteckte Datenklassengenerierungswünsche. Oder woher kommen die DGV-Daten? Den Sinn der Übung hast Du auch noch nicht verraten.
    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:


    Nächster Schritt wäre eine vernünftige Datenhaltung. Rohdaten in nem DGV sind fast immer ein Indiz für versteckte Datenklassengenerierungswünsche. Oder woher kommen die DGV-Daten? Den Sinn der Übung hast Du auch noch nicht verraten.


    Die Daten des DGV kommen aus einer Maria DB Datenbank....

    Ich erfasse Text, die in eine Datenbank rein sollen.
    Die Personen werden hier nur Zugeordnet, damit ich mir das Tippen sparen kann.

    Sprich:
    Es gibt ne Datenbank mit Personen.
    Der Code macht in den zu erfassenden Texten aus den Personen die <personen> einträge.
    Dann wir der Text in der Datenbank abgelegt und im HTML/PHP in einem Browser wieder ausgespuckt.

    Ich habe nur versucht, mit ein Tool zu basteln, um dieses ständige <person....> zu sparen.
    Nächstes Problem(chen)

    Wenn ich das jetz durchlaufen lasse und z.b. schrreibe:
    "Hans Dampf der Raucher, Dagobert Duck der Millionär, Elon Musk der Milliardär und Rudi Rüssel sitzen in einem Boot. Dagobert Duck und Elon Msuk strteiten darüber wer reicher ist."

    wird daraus:
    "<person id=1>Hans Dampf</person> der Raucher, <person id=2>Dagobert Duck</person> der Millionär, <person id=3>Elon Musk</person> der Milliardär und <person id=4>Rudi Rüssel</person> sitzen in einem Boot. <person id=2>Dagobert Duck</person> und <person id=3>Elon Musk</person> strteiten darüber wer reicher ist.""

    Die zweiten Einträge werden geändert aber nicht gefärbt.

    Ich bin aktuell noch bei Version des Codes, wo der Durchlauf zweimal stattfindet.

    die Farbe Rot ist der Moderation vorbehalten und entsprechende Passagen wurden durch Inline-CodeTags ersetzt ~VaporiZed

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

    IndexOf gibt eben nur das erste Auftreten des gesuchten Strings wieder.

    Moderatorenhinweis: Auch wenn Dein programminterner Text teilweise rot ist, gilt weiterhin hier im Forum: die Farbe Rot ist der Moderation vorbehalten ~VaporiZed
    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.