Select Range of Text in WPF RichTextBox (FlowDocument) Programmatically

I have this WPF RichTextBox and I want to programmatically select a given range of letters/words and highlight it. I've tried this, but it doesn't work, probably because I'm not taking into account some hidden FlowDocument tags or similar. For example, I want to select letters 3-8 but 2-6 gets selected):

var start = MyRichTextBox.Document.ContentStart;
var startPos = start.GetPositionAtOffset(3);
var endPos = start.GetPositionAtOffset(8);
var textRange = new TextRange(startPos,endPos);
textRange.ApplyPropertyValue(TextElement.ForegroundProperty,
    new SolidColorBrush(Colors.Blue));
textRange.ApplyPropertyValue(TextElement.FontWeightProperty, 
    FontWeights.Bold);

I've realised RichTextBox handling is a bit trickier than I thought :)

Update: I got a few answers on the MSDN forums: This thread where "dekurver" seid:

The offsets you're specifying are not character offsets but symbol offsets. What you need to do is get a TextPointer that you know is adjacent to text, then you can add character offsets.

And "LesterLobo" said:

you will need to loop through the paragraphs and inlines to find the Next and then their offsets in a loop to apply for all appearances of the specific text. note that when you edit your text would move but your highlight wouldnt move as its associated with the offset not the text. You could however create a custom run and provide a highlight for it...

Would still LOVE to see some sample code for this if someone knows their way around FlowDocuments...

EDIT I got a version of Kratz VB code working, it looks like this:

private static TextPointer GetPoint(TextPointer start, int x)
{
    var ret = start;
    var i = 0;
    while (i < x && ret != null)
    {
        if (ret.GetPointerContext(LogicalDirection.Backward) == 
TextPointerContext.Text ||
            ret.GetPointerContext(LogicalDirection.Backward) == 
TextPointerContext.None)
            i++;
        if (ret.GetPositionAtOffset(1, 
LogicalDirection.Forward) == null)
            return ret;
        ret = ret.GetPositionAtOffset(1, 
LogicalDirection.Forward);
    }
    return ret;
}

And I use it like this:

Colorize(item.Offset, item.Text.Length, Colors.Blue);

private void Colorize(int offset, int length, Color color)
{
    var textRange = MyRichTextBox.Selection;
    var start = MyRichTextBox.Document.ContentStart;
    var startPos = GetPoint(start, offset);
    var endPos = GetPoint(start, offset + length);

    textRange.Select(startPos, endPos);
    textRange.ApplyPropertyValue(TextElement.ForegroundProperty, 
new SolidColorBrush(color));
    textRange.ApplyPropertyValue(TextElement.FontWeightProperty, 
FontWeights.Bold);
}

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...)


尝试一下:

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;
}
链接地址: http://www.djcxy.com/p/61120.html

上一篇: 使用GetLineStartPosition获取WPF RichTextBox中行的结尾

下一篇: 以编程方式在WPF RichTextBox(FlowDocument)中选择文本范围