如何突出显示RichTextBox中的特定文本?

时间:2017-09-07 10:48:53

标签: c# wpf richtextbox syntax-highlighting

RichTextBox控件中,我试图通过正则表达式匹配突出显示RED颜色的特定文本。

样品:

此文字说明工作正常,并以红色阴影突出显示'Deans':

  

从客户端选择前10名*,其中MailName ='Deans'

此文本语句也可以正常工作,并以红色阴影突出显示代码:

  

从客户端选择前10名*,其中MailName ='De a ns'

但是这句话失败了:

  

从客户端选择前10名*,其中MailName ='Deans'

它失败了,因为单引号之间有空格,它会在启动TextRange的行上抛出异常

TextRange result = new TextRange(start, start.GetPositionAtOffset(word.Length)); 

例外说:

  

参数位置无效2。

请建议我一个解决方案。我在哪里弄错了?

以下是代码段:

string StringFromRichTextBox(RichTextBox rtb)
{
    TextRange textRange = new TextRange(rtb.Document.ContentStart,      
                rtb.Document.ContentEnd);

    return textRange.Text;
}

private void TextChangedEventHandler(object sender, TextChangedEventArgs e)
{
    TextRange documentRange = new TextRange(txtQueries.Document.ContentStart, txtQueries.Document.ContentEnd);
        documentRange.ClearAllProperties();

    MatchCollection match = Regex.Matches(StringFromRichTextBox(txtQueries), @"'([^']*)'");
    for (int z = 0; z < match.Count; z++)
    {
        CheckKeyword(documentRange, match[z].ToString().Trim());
    }
}

private void CheckKeyword(TextRange textRange, string word)
{
    //txtQueries.TextChanged -= this.TextChangedEventHandler;
    if (textRange.Text.Contains(word))
    {
        int offset = textRange.Text.IndexOf(word);
        if (offset < 0)
        {
            return;
        }// Not found
        else
        {
            // Try to select the text as a contiguous range
            for (TextPointer start = textRange.Start.GetPositionAtOffset(offset); start != textRange.End; start = start.GetPositionAtOffset(1))
            {
                try
                {
                    TextRange result = new TextRange(start, start.GetPositionAtOffset(word.Length));
                    if (result != null && result.Text == word)  
                    {
                        result.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Red));
                        break;
                    }
                }
                catch(Exception ex)
                {
                    throw new Exception(ex.Message);
                }
            }
        }
    }
    //txtQueries.TextChanged += this.TextChangedEventHandler;
}

错误讯息:

  

值不能为空。   参数名称:position2   在System.Windows.Documents.TextRange..ctor(TextPointer position1,TextPointer position2)

2 个答案:

答案 0 :(得分:0)

解决方案::在偏移长度上添加了4,以解释在richtextbox中出现空格的特殊隐形字符。

    var length = word.Length;
                // Try to select the text as a contiguous range
                for (TextPointer start = textRange.Start.GetPositionAtOffset(offset); start != textRange.End; start = start.GetPositionAtOffset(1))
                {
                    try
                    {

                        TextRange result = new TextRange(start, start.GetPositionAtOffset(word.Contains(" ") ? word.Length + 4: word.Length)); //Added 4 to the offset length to account for special invisible characters coming up with space in richtext box
                        if (result.Text.Trim() == word.Trim())  
                        {
                            result.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Red));
                            break;
                        }

                    }
                    catch (Exception ex)
                    {
                        throw new Exception(ex.Message);
                    }

答案 1 :(得分:0)

我在这个问题上也遇到了很多麻烦!在使用GetPositionAtOffset进行大量wtf之后,我想出了这种方法来在TextPointer中进行搜索时获得准确的RichTextBox

public static TextRange FindStringRangeFromPosition(TextPointer position, string str) {
     //what makes this work is checking the PointerContext so you avoid the markup characters   
     while (position != null) {
            if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text) {
                string textRun = position.GetTextInRun(LogicalDirection.Forward);

                // Find the starting index of any substring that matches "str".
                int indexInRun = textRun.IndexOf(str);
                if (indexInRun >= 0) {
                //since we KNOW we're in a text section we can find the endPointer by the str.Length now
                    return new TextRange(position.GetPositionAtOffset(indexInRun), position.GetPositionAtOffset(indexInRun + str.Length));
                }
            }
            position = position.GetNextContextPosition(LogicalDirection.Forward);
        }

        // position will be null if "str" is not found.
        return null;
    }