I'm trying to implement the Application.Find command for the WPF richtextbox. Let's say I'm searching for "expert". Sounds easy enough. But due to the nature of wpf, if every other letter in "expert" is bolded, then the richtextbox contains e*x*p*e*r*t* and that means six runs exist. I have a starting textPointer. What I'm trying to figure out is how to get the ending textPointer so that I can create a TextRange that I can use to create the Selection.
In this example, the starting textpointer is in the first run, and the ending textpointer should be in the last run. Is there a simple way to generate a textpointer if you know the run and the offset within the run? I tried generating it using a offset from the first textpointer but that did not work because the offset was not within the first run.
As a relative newbie to the WPF richtextbox, this one has me stumped. I imagine that this problem has already been tackled and solved. I did find one partial solution but it only worked on a single run and does not address the multiple run situation.
The idea is to find the offset of the first character (IndexOf
) and then to find the TextPointer at this index (but by counting only text characters).
public TextRange FindTextInRange(TextRange searchRange, string searchText)
{
int offset = searchRange.Text.IndexOf(searchText, StringComparison.OrdinalIgnoreCase);
if (offset < 0)
return null; // Not found
var start = GetTextPositionAtOffset(searchRange.Start, offset);
TextRange result = new TextRange(start, GetTextPositionAtOffset(start, searchText.Length));
return result;
}
TextPointer GetTextPositionAtOffset(TextPointer position, int characterCount)
{
while (position != null)
{
if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
{
int count = position.GetTextRunLength(LogicalDirection.Forward);
if (characterCount <= count)
{
return position.GetPositionAtOffset(characterCount);
}
characterCount -= count;
}
TextPointer nextContextPosition = position.GetNextContextPosition(LogicalDirection.Forward);
if (nextContextPosition == null)
return position;
position = nextContextPosition;
}
return position;
}
This is how to use the code:
TextRange searchRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);
TextRange foundRange = FindTextInRange(searchRange, "expert");
foundRange.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Red));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With