在RichTextBox中突出显示文本

13

我想使用RichTextBox,但我的第一感觉是:“它的使用太复杂了!”... 真是令人惊讶...

所以我想要在我的RichTextBox中突出显示一段文本。

我目前有以下代码:

TextRange range = new TextRange(MyTextInput.Document.ContentStart, MyTextInput.Document.ContentEnd);
range.Text = @"TOP a multiline text or file END";
Regex reg = new Regex("(top|file|end)", RegexOptions.Compiled | RegexOptions.IgnoreCase);

foreach (Match match in reg.Matches(range.Text))
{
    TextPointer start = range.Start.GetPositionAtOffset(match.Index, LogicalDirection.Forward);
    TextPointer end = range.Start.GetPositionAtOffset(match.Index + match.Length, LogicalDirection.Backward);
    // text contains the exact match I want
    string text = range.Text.Substring(match.Index, match.Length);
    // here the highlighted text isn't the text I searched...
    TextRange textrange = new TextRange(start, end);
    textrange.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Blue));
    textrange.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
}

TOP 被正确地突出显示,但是 file 或者 end 没有被突出显示,但是突出显示了我 or

有什么建议吗?

1个回答

19

要理解RichTextBox的行为,你需要想象它在幕后做了什么。虽然我不知道确切的情况,但我猜测如下:第1-2行将一个带有RunParagraph设置为RichTextBox的内容。

接着,在第一次使用ApplyPropertyValue迭代时,RichTextBox的内容就被改变了!它现在包含一个带有Span(里面包含Run)和一个RunParagraph

此外,您还需要考虑正则表达式匹配和GetPositionAtOffset之间的差异。正则表达式匹配返回字符串中字符位置的索引。

GetPositionAtOffset使用"用于计算和返回位置的符号偏移量",其中符号是:

  • TextElement元素的打开或关闭标记。
  • 包含在InlineUIContainer或BlockUIContainer中的UIElement元素。请注意,这样的UIElement始终被视为一个符号;UIElement包含的任何其他内容或元素都不会被视为符号。
  • 文本Run元素中的16位Unicode字符。

因此,您可能需要这样做:

TextRange range = new TextRange(MyTextInput.Document.ContentStart, MyTextInput.Document.ContentEnd);
range.Text = @"TOP a multiline text or file END";
Regex reg = new Regex("(top|file|end)", RegexOptions.Compiled | RegexOptions.IgnoreCase);

var start = MyTextInput.Document.ContentStart;
while (start != null && start.CompareTo(MyTextInput.Document.ContentEnd) < 0)
{
    if (start.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
    {
        var match=reg.Match(start.GetTextInRun(LogicalDirection.Forward));

        var textrange = new TextRange(start.GetPositionAtOffset(match.Index, LogicalDirection.Forward), start.GetPositionAtOffset(match.Index + match.Length, LogicalDirection.Backward));
        textrange.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Blue));
        textrange.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
        start= textrange.End; // I'm not sure if this is correct or skips ahead too far, try it out!!!
    }
    start = start.GetNextContextPosition(LogicalDirection.Forward);
}

*声明:我目前远离开发环境,尚未尝试此内容。我甚至不知道它是否能编译,但我希望如此。


2
编译成功并运行,恭喜!(感谢您的解释,但对我来说,RichTextBox目前还是一个大黑匣子...) - Arnaud F.
1
非常棒的回答,但这是一个使用var让我困惑的典型例子。因为我不熟悉这些属性,也不知道例如ContentStart是索引(可能是)还是字符或其他什么。 - Caster Troy
4
抱歉,但这种方式对于长篇文本来说太慢了。 - Heysem Katibi
我简直不敢相信为了如此简单的功能(例如与HTML相比),居然需要这么多代码。不过,代码运行得很好。非常感谢! - Edza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接