3

I have a RichTextBox in my WPF application and inside of it there is a regular Text.There are parts of that text that I want to change the color of. Example:

The file looks like that:

<note>
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>

And I want to change the color of this:<heading>Reminder</heading>

Is there a way for that to happen?

XAML of the window:

<Window x:Class="WpfConfigHelper.Framework.AdditionalWinows.XmlAfterUpdateComparator"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="XmlAfterUpdateComparator" Height="602" Width="1033">
<Grid>
    <RichTextBox Height="426" HorizontalAlignment="Left" Margin="9,42,0,0" Name="BeforeXmlUpdated_TextBox" VerticalAlignment="Top" Width="495" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"/>
    <RichTextBox Height="426" HorizontalAlignment="Left" Margin="510,42,0,0" Name="AfterXmlUpdated_TextBox" VerticalAlignment="Top" Width="490" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"/>
    <Label Content="Before Update:" Height="29" HorizontalAlignment="Left" Margin="205,12,0,0" Name="BeforeXmlUpdated_Label" VerticalAlignment="Top" Width="115" />
    <Label Content="After Update:" Height="31" HorizontalAlignment="Left" Margin="697,12,0,0" Name="AfterXmlUpdated_Label" VerticalAlignment="Top" Width="87" />
    <Label Content="Do you agree to perform the changes from the right text box?" Height="33" HorizontalAlignment="Left" Margin="338,485,0,0" Name="DoYouAgreeWithChanges_Label" VerticalAlignment="Top" Width="497" />
    <Button Content="Yes" Height="27" HorizontalAlignment="Left" Margin="308,524,0,0" Name="AgreedWithChanges_Button" VerticalAlignment="Top" Width="196" Click="AgreedWithChanges_Button_Click" />
    <Button Content="No" Height="29" HorizontalAlignment="Left" Margin="516,524,0,0" Name="DisagreedWithChanges_Button" VerticalAlignment="Top" Width="221" Click="DisagreedWithChanges_Button_Click" />
    <Label Content="Text removed" Height="39" HorizontalAlignment="Left" Margin="12,474,0,0" Name="label1" VerticalAlignment="Top" Width="177" Foreground="Red" FontSize="13"/>
    <Label Content="Text inserted" Height="41" HorizontalAlignment="Left" Margin="906,477,0,0" Name="label2" VerticalAlignment="Top" Width="93" Foreground="Green" FontSize="13"/>
</Grid>


It was not a long time ago I saw a code that was using Regular expressions that used to map the whole phrase and change its color in the text but I can not see it happening here.The text is static and there is no formatting at all.

Do you think that I could transform it somehow so I can format it and then show it in the RichTextBox formatted with the colord, fonts etc.?

ChrisF
  • 134,786
  • 31
  • 255
  • 325
mathinvalidnik
  • 1,566
  • 10
  • 35
  • 57

1 Answers1

0

In RichTextBox you can modify the font for particular text region using TextRange. TextRang need start and end pointer. You can't get these pointer in the existing RichTextBox content by using index if already formatting is applied for some region of text since RichTextBox is consider the text content as symbols not characters. So, I suggest you to create a custom RichTextBox for your problem. Here I have created CustomRichTextBox which is derived from RichTextBox. Method ApplyPropertyValue is used to format the specified region of text.

public class CustomRichTextBox : RichTextBox
{
    private readonly List<FormattingTag> formattingTags = new List<FormattingTag>();

    public IEnumerable<FormattingTag> FormattingTags
    {
        get { return this.formattingTags; }
    }

    public void ApplyPropertyValue(int startIndex, int length, DependencyProperty formattingProperty, object value)
    {
        TextRange documentRange = new TextRange(this.Document.ContentStart, this.Document.ContentEnd);
        documentRange.ClearAllProperties();
        string documentText = documentRange.Text;
        if (startIndex < 0 || (startIndex + length) > documentText.Length)
        {
            return;
        }

        this.CaretPosition = this.Document.ContentStart;
        this.formattingTags.Add(FormattingTag.GetTag(this.Document.ContentStart, startIndex, length, formattingProperty, value));

        foreach (var formattingTag in formattingTags)
        {
            formattingTag.ApplyFormatting();
        }
    }
}

In the custom control you have to maintain all the applied formatting. For that I created the below class which holds the formatting information.

public class FormattingTag
{
    private int start;
    private int length;

    private FormattingTag(int start, int length)
    {
        this.start = start;
        this.length = length;
    }

    public int Start
    {
        get{ return this.start; }
    }

    public int Length
    {
        get { return this.length; }
    }

    public TextPointer StartPosition { get; private set; }

    public TextPointer EndPosition { get; private set; }

    public DependencyProperty FormattingProperty { get; private set; }

    public object Value { get; private set; }

    public static FormattingTag GetTag(TextPointer start, int startIndex, int length, DependencyProperty formattingProperty, object value)
    {
        while (start.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.Text)
        {
            start = start.GetNextContextPosition(LogicalDirection.Forward);
        }

        TextPointer contentStart = start.GetPositionAtOffset(startIndex);
        TextPointer contentEnd = contentStart.GetPositionAtOffset(length);
        FormattingTag tag = new FormattingTag(startIndex, length);
        tag.StartPosition = contentStart;
        tag.EndPosition = contentEnd;
        tag.FormattingProperty = formattingProperty;
        tag.Value = value;
        return tag;
    }

    public void ApplyFormatting()
    {
        TextRange range = new TextRange(this.StartPosition, this.EndPosition);
        range.ApplyPropertyValue(this.FormattingProperty, this.Value);
    }
}

You can apply formatting for the text like below.

this.richTextBox.ApplyPropertyValue(2, 5, TextElement.ForegroundProperty, Brushes.Red);
this.richTextBox.ApplyPropertyValue(8, 11, TextElement.ForegroundProperty, Brushes.Blue);
petchirajan
  • 4,152
  • 1
  • 18
  • 20