Select Range of Text in WPF RichTextBox (FlowDocument) Programmatically
Public Function GoToPoint(ByVal start As TextPointer, ByVal x As Integer) As TextPointer
Dim out As TextPointer = start
Dim i As Integer = 0
Do While i < x
If out.GetPointerContext(LogicalDirection.Backward) = TextPointerContext.Text Or _
out.GetPointerContext(LogicalDirection.Backward) = TextPointerContext.None Then
i += 1
End If
If out.GetPositionAtOffset(1, LogicalDirection.Forward) Is Nothing Then
Return out
Else
out = out.GetPositionAtOffset(1, LogicalDirection.Forward)
End If
Loop
Return out
End Function
Try this, this should return a text pointer for the given char offset. (Sorry its in VB, but thats what I am working in...)
Could not find a solution with acceptable performance solution to this problem for a long time. Next sample works in my case with the highest performance. Hope it will help somebody as well.
TextPointer startPos = rtb.Document.ContentStart.GetPositionAtOffset(searchWordIndex, LogicalDirection.Forward);
startPos = startPos.CorrectPosition(searchWord, FindDialog.IsCaseSensitive);
if (startPos != null)
{
TextPointer endPos = startPos.GetPositionAtOffset(textLength, LogicalDirection.Forward);
if (endPos != null)
{
rtb.Selection.Select(startPos, endPos);
}
}
public static TextPointer CorrectPosition(this TextPointer position, string word, bool caseSensitive)
{
TextPointer start = null;
while (position != null)
{
if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
{
string textRun = position.GetTextInRun(LogicalDirection.Forward);
int indexInRun = textRun.IndexOf(word, caseSensitive ? StringComparison.InvariantCulture : StringComparison.InvariantCultureIgnoreCase);
if (indexInRun >= 0)
{
start = position.GetPositionAtOffset(indexInRun);
break;
}
}
position = position.GetNextContextPosition(LogicalDirection.Forward);
}
return start;
}
Try that :
var textRange = MyRichTextBox.Selection;
var start = MyRichTextBox.Document.ContentStart;
var startPos = start.GetPositionAtOffset(3);
var endPos = start.GetPositionAtOffset(8);
textRange.Select(startPos, endPos);
textRange.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Blue));
textRange.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
I tried using the solution posted by KratzVB but found that it was ignoring newlines. If you want to count \r and \n symbols then this code should work:
private static TextPointer GetPoint(TextPointer start, int x)
{
var ret = start;
var i = 0;
while (ret != null)
{
string stringSoFar = new TextRange(ret, ret.GetPositionAtOffset(i, LogicalDirection.Forward)).Text;
if (stringSoFar.Length == x)
break;
i++;
if (ret.GetPositionAtOffset(i, LogicalDirection.Forward) == null)
return ret.GetPositionAtOffset(i-1, LogicalDirection.Forward)
}
ret=ret.GetPositionAtOffset(i, LogicalDirection.Forward);
return ret;
}