2

I'm trying to recolour all the numbers in a WPF RichTextBox to be coloured differently. I've been following this tutorial, but I find that letters in the text are highlighted almost at random. This is the handler I have so far:

private void DescriptionText_TextChanged(object sender, TextChangedEventArgs e)
{
    var range = new TextRange(DescriptionText.Document.ContentStart, DescriptionText.Document.ContentEnd);
    var regex = new Regex("[0-9]+");
    var num_ranges = new List<TextRange>();

    // add all the ranges with numbers
    foreach (Match match in num_reg.Matches(range.Text))
    {
        var start = range.Start.GetPositionAtOffset(match.Index);
        var end   = range.Start.GetPositionAtOffset(match.Index + match.Length);

        num_ranges.Add(new TextRange(start, end));
    }

    // unsuscribe before making changes
    DescriptionText.TextChanged -= this.DescriptionText_TextChanged;

    range.ClearAllProperties();
    range.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Black));

    foreach (var r in num_ranges)
    {
        r.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Red));
    }

    DescriptionText.TextChanged += this.DescriptionText_TextChanged;
}
ymbcKxSw
  • 315
  • 4
  • 10
  • 1
    I had a similar issue and it took a lot of trial and error to figure out what was going on. When you highlight like this, there is sort of an "invisible" color tag that is inserted (I'm not sure the technical term for this, I apologize). I'd suggest following this answer: https://stackoverflow.com/a/18149516/6538434 – eye_am_groot May 10 '18 at 18:15

2 Answers2

0

Try this

DescriptionText.TextChanged -= this.DescriptionText_TextChanged;
var regExp = new Regex(@"^-*[0-9,\.]+$");
foreach (Match match in regExp.Matches(rtb.Text))
    {
        var textRange = rtb.Selection;
        textRange.Select(match.Index, match.Length);
        textRange.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Red));
        //rtb.SelectionColor = Color.Red;
    }
DescriptionText.TextChanged += this.DescriptionText_TextChanged;
Lion King
  • 495
  • 5
  • 14
  • Your answer works for the Windows Forms [RichTextBox](https://msdn.microsoft.com/en-us/library/system.windows.forms.richtextbox(v=vs.110).aspx) but the API is not doesn't let me select in this way for WPF [RichTextBox](https://msdn.microsoft.com/en-us/library/system.windows.forms.richtextbox(v=vs.110).aspx) – ymbcKxSw May 11 '18 at 14:54
0

After making modifications to the questions linked in the comments, I got the following to work: (I've given the relevant codebehind)

public class Tag
{
    public TextPointer StartPosition;
    public TextPointer EndPosition;
}

private void DescriptionText_TextChanged(object sender, TextChangedEventArgs e)
{
    string text;

    DescriptionText.TextChanged -= this.DescriptionText_TextChanged;
    var range = new TextRange(DescriptionText.Document.ContentStart, DescriptionText.Document.ContentEnd);
    range.ClearAllProperties();

    var tags = new List<Tag>();

    TextPointer navigator = DescriptionText.Document.ContentStart;
    while (navigator.CompareTo(DescriptionText.Document.ContentEnd) < 0)
    {
        TextPointerContext context = navigator.GetPointerContext(LogicalDirection.Backward);
        if (context == TextPointerContext.ElementStart && navigator.Parent is Run)
        {
            text = ((Run)navigator.Parent).Text;
            if (text != "")
                tags.AddRange(CheckWordsInRun(text, (Run)navigator.Parent));
        }
        navigator = navigator.GetNextContextPosition(LogicalDirection.Forward);
    }

    foreach (Tag tag in tags)
    {
        var r = new TextRange(tag.StartPosition, tag.EndPosition);
        r.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Red));
    }
    DescriptionText.TextChanged += this.DescriptionText_TextChanged;
}

private List<Tag> CheckWordsInRun(string text, Run theRun)
{
    List<Tag> m_tags = new List<Tag>();

    for (int i = 0; i < text.Length; i++)
    {
        if (Char.IsNumber(text[i]))
        {
            Tag t = new Tag();
            t.StartPosition = theRun.ContentStart.GetPositionAtOffset(i, LogicalDirection.Forward);
            t.EndPosition = theRun.ContentStart.GetPositionAtOffset(i + 1, LogicalDirection.Backward);
            m_tags.Add(t);
        }
    }
    return m_tags;
}
ymbcKxSw
  • 315
  • 4
  • 10