突出显示 FlowDocument 中的部分文本
Posted
技术标签:
【中文标题】突出显示 FlowDocument 中的部分文本【英文标题】:Highlight parts of text in FlowDocument 【发布时间】:2013-09-16 15:06:28 【问题描述】:我想根据搜索结果突出显示FlowDocument
中的某些文本部分。我正在做的是获取在FlowDocument
的文本中出现搜索词的索引,然后在从找到的索引开始的文本范围上应用背景色,以找到的索引+搜索词长度结束。
TextRange content = new TextRange(myFlowDocument.ContentStart,
myFlowDocument.ContentEnd);
List<int> highlights = GetHighlights(content.Text, search);
foreach (int index in highlights)
var start = myFlowDocument.ContentStart;
var startPos = start.GetPositionAtOffset(index);
var endPos = start.GetPositionAtOffset(index + search.Length);
var textRange = new TextRange(startPos, endPos);
textRange.ApplyPropertyValue(TextElement.BackgroundProperty,
new SolidColorBrush(Colors.Yellow));
TextRange newRange = new TextRange(myFlowDocument.ContentStart,
newDocument.ContentEnd);
FlowDocument fd = (FlowDocument)XamlReader.Parse(newRange.Text);
问题是,我正在搜索文档文本中的索引,但是当我返回 FlowDocument
时,添加了 xaml 标记并且我看到突出显示移动了。
我该如何解决?
【问题讨论】:
【参考方案1】:最后,受到 user007 回答的启发,在进行了一些修改后,我设法突出显示了 FlowDocument 中字符串的所有出现。这是我的代码:
for (TextPointer position = newDocument.ContentStart;
position != null && position.CompareTo(newDocument.ContentEnd) <= 0;
position = position.GetNextContextPosition(LogicalDirection.Forward))
if (position.CompareTo(newDocument.ContentEnd) == 0)
return newDocument;
String textRun = position.GetTextInRun(LogicalDirection.Forward);
StringComparison stringComparison = StringComparison.CurrentCulture;
Int32 indexInRun = textRun.IndexOf(search, stringComparison);
if (indexInRun >= 0)
position = position.GetPositionAtOffset(indexInRun);
if (position != null)
TextPointer nextPointer = position.GetPositionAtOffset(search.Length);
TextRange textRange = new TextRange(position, nextPointer);
textRange.ApplyPropertyValue(TextElement.BackgroundProperty,
new SolidColorBrush(Colors.Yellow));
【讨论】:
【参考方案2】:您需要使用GetNextContextPosition(LogicalDirection.Forward)
进行迭代并获取TextPointer
,将此与先前的TextPointer
一起使用以构造TextRange
。在这个TextRange
上,你可以应用你的逻辑。
你不能做的是使用来自FlowDocument
的单个 TextRange 来搜索文本。 FlowDocument
不仅仅是文字:
private void Button_Click(object sender, RoutedEventArgs e)
String search = this.content.Text;
TextPointer text = doc.ContentStart;
while (true)
TextPointer next = text.GetNextContextPosition(LogicalDirection.Forward);
if (next == null)
break;
TextRange txt = new TextRange(text, next);
int indx = txt.Text.IndexOf(search);
if (indx > 0)
TextPointer sta = text.GetPositionAtOffset(indx);
TextPointer end = text.GetPositionAtOffset(indx + search.Length);
TextRange textR = new TextRange(sta, end);
textR.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(Colors.Yellow));
text = next;
更新:
它并非始终有效,例如,如果您有列表,则特殊字符 (\t) 会被 IndexOf
计算在内,但 GetPositionAtOffset
不会将它们计算在内:
• ListItem 1
• ListItem 2
• ListItem 3
这一行:
int indx = txt.Text.IndexOf(search);
可以替换为:
int indx = Regex.Replace(txt.Text,
"[^a-zA-Z0-9_.]+", "", RegexOptions.Compiled).IndexOf(search);
【讨论】:
非常感谢您的帮助。我正在尝试您的代码,但它仅突出显示搜索文本的第一次出现。我现在正在尝试对其进行修改以显示所有出现的情况。【参考方案3】:kzub
的答案似乎对我不起作用,因此我还创建了一个扩展 user007
的解决方案,以突出显示 TextPointer 文本中子字符串的所有实例。它还会忽略大小写并突出显示所有匹配项:
public static void HighlightWords(TextPointer text, string searchWord, string stringText)
int instancesOfSearchKey = Regex.Matches(stringText.ToLower(), searchWord.ToLower()).Count;
for (int i = 0; i < instancesOfSearchKey; i++)
int lastInstanceIndex = HighlightNextInstance(text, searchWord);
if (lastInstanceIndex == -1)
break;
text = text.GetPositionAtOffset(lastInstanceIndex);
private static int HighlightNextInstance(TextPointer text, string searchWord)
int indexOfLastInstance = -1;
while (true)
TextPointer next = text.GetNextContextPosition(LogicalDirection.Forward);
if (next == null)
break;
TextRange newText = new TextRange(text, next);
int index = newText.Text.ToLower().IndexOf(searchWord.ToLower());
if (index != -1)
indexOfLastInstance = index;
if (index > 0)
TextPointer start = text.GetPositionAtOffset(index);
TextPointer end = text.GetPositionAtOffset(index + searchWord.Length);
TextRange textRange = new TextRange(start, end);
textRange.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(Colors.Yellow));
text = next;
return indexOfLastInstance;
【讨论】:
以上是关于突出显示 FlowDocument 中的部分文本的主要内容,如果未能解决你的问题,请参考以下文章