I want to highlight some parts of text in a FlowDocument
based on the search results. What I am doing is getting the indexes where the searched word occures in the text of the FlowDocument
and then apply background color on the text range starting at the found index, ending at the found index + search word length.
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);
The problem is, that I am searching indexes in the text of the document but when I'm returning the FlowDocument
the xaml tags are added and I see the highlights moved.
How can I fix it?
You need to iterate using
GetNextContextPosition(LogicalDirection.Forward)
and getTextPointer
, use this one with previousTextPointer
to constructTextRange
. On thisTextRange
you can apply your logic.What you can't do is use single TextRange from
FlowDocument
for searching text.FlowDocument
is not only text:UPDATE: it does not work allways, for example if you have list, special characters (\t) are counted by
IndexOf
, butGetPositionAtOffset
doesn't count them in:this line:
could be replaced with:
kzub
's answer did not seem to work for me so I also created a solution expanding onuser007
to highlight all instances of a substring in TextPointer text. It also ignores case and will highlight all matches:Finaly, inspired by the answer of user007, after making some modifications I managed to highlight all the occurences of a string in a FlowDocument. Here is my code: