WPF Richtextbox eigene Formatierungen definieren

  • WPF

Es gibt 40 Antworten in diesem Thema. Der letzte Beitrag () ist von Translating-IT.

    WPF Richtextbox eigene Formatierungen definieren

    Hallo,

    Kann ich in WPF für eine Richtextbox eigene Formatierungen definieren, wie man es in CSS für HTML kann? Ich möchte bei bestimmten Ereignissen, Wörter oder Wortgruppen programmatisch auf unterschiedliche Weisen unterstreichen.

    z. B. farbige Wellenlinie (unterschiedliche Farben), farbige gepunktete Linie, farbige gestrichelte Linie, usw.

    LG,
    Pascal
    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.
    Hallo @Translating-IT

    Ich weis nicht ob es das richtige für dich ist aber ich denke bei sowas im Grunde sofort an Avalon.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Hallo Sascha,

    nein, leider nicht. Es geht nicht wirklich um Syntaxhervorhebung. Die Strings müssen immer je nach Kontext, der sich aber jedes Mal ändert, geprüft werden. Die Regeln werden oft extra dafür definiert.
    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.
    Vollzitat des direkten Vorposts an dieser Stelle entfernt ~VaporiZed

    Ja, daran hatte ich auch gedacht. Du könntest mittels:

    VB.NET-Quellcode

    1. IF EingabeString.Contains(...) ... THEN
    2. ... 'Hier die Formatierung
    3. END IF


    arbeiten. Und statt Contains kann auch StartsWith, EndsWith und anderes genutzt werden. So könntest du auch ohne Framework oder ähnliches arbeiten.

    Und eine RTB arbeitet auch mit sogenannten Runs (innerhalb derer kannst du die gewünschte Formatierung auswählen und mitgeben)
    und dann fügst du diesne Run deiner RTB hinzu

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

    An eine Stingbuilder oder so ähnlich hatte ich auch gedacht, das Problem ist, dass ich nicht weiß, wie ich diese speziellen Formatierungen erhalte.

    Ich kann zwar unterstreichen (ForegroundProperty, underline) oder farblich hervorheben (ForegroundProperty, Brushes.Red), … (also die Standardformatierungen). Aber ich habe keine Möglichkeit gefunden, bei underline eine Wellenlinie oder Strichelchen oder Punkte anzugeben, oder die Farbe der Wellenlinie zu definieren.

    Oder denke ich da schon wieder zu kompliziert?

    Edit: sorry, Stringbuilder und dann nach Einfügen in die RTB per Selection die Formatierung vergeben war mein Gedanke.
    Im Stringbuilder arbeite ich dann mit <b>, <i> usw.? Bleibt aber immer noch die Frage zu den Sonderformatierungen der Unterstreichung …
    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.
    Wenn ich in XAML eine gewellte Linie so definiere:

    VB.NET-Quellcode

    1. <Grid.Resources>
    2. <VisualBrush x:Key="WavyBrush" Viewbox="0,0,3,2" ViewboxUnits="Absolute" Viewport="0,0.8,6,4" ViewportUnits="Absolute" TileMode="Tile">
    3. <VisualBrush.Visual>
    4. <Path Data="M 0,1 C 1,0 2,2 3,1" Stroke="Red" StrokeThickness="0.2" StrokeEndLineCap="Square" StrokeStartLineCap="Square" />
    5. </VisualBrush.Visual>
    6. </VisualBrush>
    7. </Grid.Resources>


    kann ich dann vom Code Behind darauf zugreifen und die Formatierung auf einen String anwenden?
    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.
    Ja, du kannst generell im Code-Behind immer darauf zugreifen, sofern deine Ressourcen einem Style oder einem Key zugeordnet sind (ich denke x:Key passt hier besser). Die Frage, die sich mir jedoch stellt ist, ob es möglich ist, einem Text eine Ressource zuzuweisen. Aber theoretisch müsste der Underline ja auch irgendwo definiert sein. Vielleicht kann man dessen Style ja auch überschreiben. ich mach mich mal schlau

    PadreSperanza schrieb:

    Vielleicht kann man dessen Style ja auch überschreiben


    überschreiben würde nur bedingt helfen, da ich ja auch andere Formatierungen mit Wellenlinie benötige. Oder habe ich Dich da jetzt falsch verstanden?
    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.
    Na ja, in WPF kannst du generell Styles überschreiben, auch wie sie aussehen oder was sie präsentieren sollen (zum Beispiel kann man Buttons mit runden Ecken ausstatten, wenn man den Style überschreibt). Der Clou ist, dass man nicht nur generell alle Styles überschreiben kann, sondern man kann sie mittels x:Key auch präzise ansprechen. Also nur, wer den x:Key bekommt, ändert seinen Style entsprechend.

    Ich habe mal versucht, mich reinzulesen, jedoch finde ich derzeit noch nicht viel, um Underline als Inline zu überschreiben. Allerdings habe ich die Methode, die du gefunden / gepostet hast, ausgetestet und sie... funktioniert. Man muss wohl nur noch am Data etwas feilen:

    Aber wenn du mittels Resource einbindest:

    XML-Quellcode

    1. ​<Window.Resources>
    2. <VisualBrush x:Key="Wave" Viewbox="0,0,1,0.9">
    3. <VisualBrush.Visual>
    4. <Path Data="M 0,2 L 2,0 4,2 6,0 8,2 10,0 12,2" Stroke="Red"/>
    5. </VisualBrush.Visual>
    6. </VisualBrush>
    7. </Window.Resources>


    dann kannst du einer Textbox zum Beispiel das hinzufügen:

    XML-Quellcode

    1. <TextBlock
    2. FontSize="12">
    3. Bumm
    4. <TextBlock.TextDecorations>
    5. <TextDecoration PenThicknessUnit="FontRecommended">
    6. <TextDecoration.Pen>
    7. <Pen Brush="{StaticResource Wave}" Thickness="10">
    8. </Pen>
    9. </TextDecoration.Pen>
    10. </TextDecoration>
    11. </TextBlock.TextDecorations>
    12. </TextBlock>


    das ändert allerdings den gesamten Text entsprechend ab und nicht nur dein gewünschtes Format. Aber wirklich elegant finde ich das eigentlich auch nicht. Wenn du das als Style irgendwie ablegen könntest, könntest du das im Codebehind hinzufügen. Aber wirklich gut sieht es dennoch nicht aus.

    PadreSperanza schrieb:

    Aber wirklich elegant finde ich das eigentlich auch nicht.


    für ganze Texte ist es ja auch nicht gedacht. ;) Nee, ich muss mir eh noch ein paar Dinge dazu ausdenken und ausprobieren. Für den gedachten Zweck passt es aber an sich recht gut (die Farben und diverse andere Formatierungen waren ja schon im Netz vorgegeben und ich habe es noch nicht angepasst, da ich es erst zum Laufen bringen möchte). Den Nutzern hat es in einer früheren HTML-Version mit so ähnlichen Formatierungen gefallen. Aber für die neue Version (WPF) ist noch nix in Stein gemeisselt. Wenn ich das in dieser Form irgendwie in den Code behind einbinden kann, kann ich es ja (hoffentlich) nach belieben abändern.

    Na, dann schau ich mir mal an, was es mit den Styles auf sich hat. Man lernt immer wieder dazu …
    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.
    Optional (ich weiß, ist keine Curly Line) kann man aber gestrichelte Unterstreichungen machen. Das unterstützt WPF von selbst, sogar mit Farbverlauf:

    java2s.com/Tutorial/CSharp/047…edecorationwithdashes.htm

    java2s.com/Tutorial/CSharp/047…halineargradientbrush.htm

    kann auch gemischt werden.
    an sich funktioniert ja die Wellenlinie, wie Du ja selbst probiert hast. Das Problem ist aber auch bei diesen beiden Möglichkeinten, wie ich das vom Code behind aus auf Strings anwenden kann. Hier wird ja auch wieder alles nur in der XAML definiert. Interessant wäre noch eine gepunktelte Linie.

    EDIT: wobei die beiden Codeschnippsel ja für TextBlock erstellt wurden. Aber sollte für RTB auch umsetzbar sein.
    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.
    ja, ist für eine RTB auch umsetzbar. Eine RTB unterstützt ja auch Formate. Ich hab mal schnell was gebastelt:Einfach eine RTB genommen und im WPF eingefügt:

    XML-Quellcode

    1. <Grid><RichTextBox x:Name="DieEineBox"></RichTextBox></Grid>


    Im Codebehind habe ich nun folgendes gemacht:

    Einen neuen Paragraphen erstellt:

    C#-Quellcode

    1. var para = new Paragraph()

    VB.NET-Quellcode

    1. Dim para as new Paragraph


    Diesem Paragraphen kannst du nun mittels Inlines neue Elemente hinzufügen:

    C#-Quellcode

    1. para.Inlines.Add(new Run("Dies ist ein Test") { TextDecorations = TextDecorations.Underline });
    2. DieEineBox.Document.Blocks.Add(para);

    VB.NET-Quellcode

    1. Para.Inlines.Add(New Run("Dies ist ein Test") With {.TextDecorations = TextDecorations.Underline})
    2. DieEineBox.Document.Blocks.Add(Para)


    Das war nun ein einfacher Paragraph, jetzt erstelle ich einen neuen Paragraphen, der TextDecorations enthält. Hierfür müssen wir eine neue TextDecorationsCollections erstellen, die alle Decorations enthält:

    C#-Quellcode

    1. //Erstellt neuen Paragraphen
    2. para = new Paragraph();
    3. //neue Collection
    4. TextDecorationCollection tDC = new TextDecorationCollection();
    5. //neue Decoration
    6. TextDecoration tD = new TextDecoration(TextDecorationLocation.Underline,
    7. new Pen() { Brush = Brushes.Red, DashStyle = DashStyles.DashDotDot },
    8. 0.0,
    9. TextDecorationUnit.FontRecommended,
    10. TextDecorationUnit.FontRecommended
    11. );
    12. //Hinzufügen der Decoration zur Deco-Collection
    13. tDC.Add(tD);
    14. //Hinzufügen eines neuen Inline-Elements mit der angelegten Collection als TextDecoration
    15. para.Inlines.Add(new Run("Dies ist ein zweiter Test") {FontSize = 36 , TextDecorations = tDC });


    VB.NET-Quellcode

    1. 'Erstellt neuen Paragraphen
    2. Para = New Paragraph
    3. 'Neue Collection
    4. Dim TDC As New TextDecorationCollection
    5. 'neue Decoration
    6. Dim TD As New TextDecoration(TextDecorationLocation.Underline, New Pen With {.Brush = Brushes.Red, .DashStyle = DashStyles.DashDotDot}, 0.0, TextDecorationUnit.FontRecommended, TextDecorationUnit.FontRecommended)
    7. 'Hinzufügen der Decoration zur Deco-Collection
    8. TDC.Add(TD)
    9. 'Hinzufügen eines neuen Inline-Elements mit der angelegten Collection als TextDecoration
    10. Para.Inlines.Add(New Run("Dies ist ein zweiter Test") With {.FontSize = 36, .TextDecorations = TDC})


    Und da wir nicht nur in Paragraphen, sondern auch im selben Inline mit unterschiedlichen Variationen arbeiten können, habe ich einfach weitere Inlines mit anderen Decorations hinzugefügt. Hierfür wird einfach eine neue Collection aus der alten gemacht und eine neue Decoration hinzugefügt:

    C#-Quellcode

    1. //Neue Collection
    2. tDC = new TextDecorationCollection();
    3. //Neue Decoration
    4. tD = new TextDecoration(TextDecorationLocation.Underline,
    5. new Pen() { Brush = Brushes.Green, DashStyle = DashStyles.Dot },
    6. 0.0,
    7. TextDecorationUnit.FontRecommended,
    8. TextDecorationUnit.FontRecommended
    9. );
    10. //Da beide neu sind, müssen wir sie wieder hinzufügen
    11. tDC.Add(tD);
    12. //hier wird dem Paragraph ein weiteres Inline angehangen mit anderer Decoration
    13. para.Inlines.Add(new Run(" mit anderen Formatierungen") { FontSize = 14, TextDecorations = tDC });
    14. //Zum Schluss muss der Paragraph nur noch an die RTB angefügt werden
    15. DieEineBox.Document.Blocks.Add(para);



    VB.NET-Quellcode

    1. 'Neue Collection
    2. TDC = New TextDecorationCollection
    3. 'Neue Decoration
    4. TD = New TextDecoration(TextDecorationLocation.Underline, New Pen With {.Brush = Brushes.Green, .DashStyle = DashStyles.Dash}, 0.0, TextDecorationUnit.FontRecommended, TextDecorationUnit.FontRecommended)
    5. 'Da beide neu sind, müssen wir sie wieder hinzufügen
    6. TDC.Add(TD)
    7. 'hier wird dem Paragraph ein weiteres Inline angehangen mit anderer Decoration
    8. Para.Inlines.Add(New Run(", mit anderen Formatierungen") With {.FontSize = 14, .TextDecorations = TDC})
    9. 'Zum Schluss muss der Paragraph nur noch an die RTB angefügt werden
    10. DieEineBox.Document.Blocks.Add(Para)


    Wie du siehst, ist es schon möglich, eigene Formatierungen in die RTB anzufügen. Es ist eben nur etwas Aufwand, das erstmal zu schreiben. Aber wenn du das auslagerst in eine eigene Funktion, sodass entsprechende TextDecorations angefügt werden, sollte das eigentlich funktionieren.

    Es gibt auch noch den sogenannten DashCap

    Quellcode

    1. DashCap = PenLineCap.Round


    hier kannst du aussuchen, ob es rund, eckig, dreieckig oder glatt verlaufen soll. Einzig mit der gerenderten Größe müsstest du nochmal schauen, wie man das am besten hinbekommt.
    Setzt du den letzten Teil der Decoration auf TextDecorationUnit.FontRenderingEmSize, wird es zu groß, aber auch besser erkennbar :P

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

    Danke. Bin heute nicht dazu gekommen viel zu schauen, da auf der Arbeit einiges los war.

    Ich habe mal mit Deinem Code rumgespielt und bin drauf gekommen, dass die reinen Punkte wohl die beste Lösung darstellen, wenn ich es nicht schaffe eine Wellenlinie zu zaubern. Deinen Code habe ich folgendermaßen angepasst, um das für mich beste Ergebnis zu erzielen, das am wenigsten Augenkrebs verursacht. An sich nur Thickness und den Abstand zum Text angepasst. ;)

    VB.NET-Quellcode

    1. Dim TDC As New TextDecorationCollection
    2. 'neue Decoration
    3. Dim TD As New TextDecoration(TextDecorationLocation.Underline, New Pen With {.Brush = Brushes.Red, .DashStyle = DashStyles.Dot, .Thickness = 2}, 1.0, TextDecorationUnit.FontRecommended, TextDecorationUnit.FontRecommended)
    4. 'Hinzufügen der Decoration zur Deco-Collection
    5. TDC.Add(TD)
    6. 'Hinzufügen eines neuen Inline-Elements mit der angelegten Collection als TextDecoration
    7. para.Inlines.Add(New Run("Dies ist ein zweiter Test") With {.FontSize = 16, .TextDecorations = TDC})

    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.
    Na siehst du, da hast du dann ja doch das hinbekommen, was du brauchst :)

    Wenn du nun als statische Klasse eine TextDecorationCollection erstellst, in der diese TextDecoration enthalten ist, kannst du jederzeit darauf zurückgreifen und kannst sie an deinen gewünschten Text anhängen, dann wird dieser unterstrichen. Zum Beispiel wenn du den gewünschten Text markierst und eine Schaltfläche hast, zum Unterstreichen, dann kannst du mittels "Selection" dieses Markup anhängen


    BTW: Wenn du neben Underline auch noch weitere, zusätzliche Decorations haben möchtest, musst du lediglich weitere TextDecorations erstellen und diese der Collection (in meinem Beispiel TDC) hinzufügen und dann werden alle enthaltenen Decorations angewendet.
    Ich versuche gerade die Wellenlinie umzusetzen, aber 2 Zeilen bekomm ich nicht in VB umgewandelt:

    VB.NET-Quellcode

    1. Dim screenpos As Rect = rtb_targettext.Selection.Start.GetCharacterRect(LogicalDirection.Forward)
    2. Dim offset As Double = screenpos.Top + rtb_targettext.VerticalOffset
    3. rtb_targettext.ScrollToVerticalOffset(offset - (rtb_targettext.ActualHeight / 2))
    4. Dim path_pen As Pen = New Pen(New SolidColorBrush(Colors.Red), 0.2)
    5. path_pen.EndLineCap = PenLineCap.Square
    6. path_pen.StartLineCap = PenLineCap.Square
    7. Dim path_start As Point = New Point(0, 1)
    8. Dim path_segment As BezierSegment = New BezierSegment(New Point(1, 0), New Point(2, 2), New Point(3, 1), True)
    9. Dim path_figure As PathFigure = New PathFigure(path_start, New PathSegment() { path_segment }, False)
    10. Dim path_geometry As PathGeometry = New PathGeometry(New PathFigure() { path_figure })
    11. Dim squiggly_brush As DrawingBrush = New DrawingBrush()
    12. squiggly_brush.Viewport = New Rect(0, 0, 6, 4)
    13. squiggly_brush.ViewportUnits = BrushMappingMode.Absolute
    14. squiggly_brush.TileMode = TileMode.Tile
    15. squiggly_brush.Drawing = New GeometryDrawing(Nothing, path_pen, path_geometry)


    Aus irgendeinem mir unerklärlichen Grund funktionieren seit ein paar Tagen keine Code Convert C# > VB.net nicht mehr bei mir (unabhängig vom Browser)

    Edit: Den Code habe ich nun hoffentlich korrekt umgesetzt (Änderungen implementiert), einen Converter der funktioniert, habe ich auch wieder gefunden.

    jetzt muss ich nur noch rausfinden, wie ich den Code in die RTB implementieren kann
    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Translating-IT“ ()

    Mein Edit hat sich mit Deiner Antwort überschnitten ;) Die eckigen Klammern waren schuld. Aber ich weiß noch nicht, wie ich das jetzt in die RTB umsetzen kann.
    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.
    okay, darauf habe ich nicht geachtet. Ich hatte primär darauf geachtet, dass er eigentlich IEnumerable haben wollte. Deshalb habe ich vorher wieder Collections erstellt, das hinzugefügt und schon meckerte er nicht mehr.

    Allerdings habe ich noch nicht verstanden, was du genau vor hast damit.