Как выбрать текст RichTextBox с учетом индекса и длины

Если вам предоставляется только указатель и длина (или EndIndex) определенного текста, как вы это делаете в WPF-версии RichTextBox?

Это очень удобно в текстовом поле, так как вы можете вызвать Textbox.Select(startIndex, Length), но я не вижу ничего эквивалентного в RTB.

Изменить: я нашел ответ на выбор

internal string Select(RichTextBox rtb, int index, int length)
        {
            TextRange textRange = new TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd);

            if (textRange.Text.Length >= (index + length))
            {
                TextPointer start = textRange.Start.GetPositionAtOffset(index, LogicalDirection.Forward);
                TextPointer end = textRange.Start.GetPositionAtOffset(index + length, LogicalDirection.Backward);
                rtb.Selection.Select(start, end);
            }
            return rtb.Selection.Text;
        } 

Однако, когда я пытаюсь выделить строку после того, как был сделан выбор:

rtb.Selection.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(Colors.LightBlue));

Функция подсветки работает только при первой попытке и разрывается после второй попытки. Кто-нибудь знает причину этого?

Ответ 1

Хорошо, этот вопрос старый, но я наконец нашел ответ, поэтому я поставил его здесь.

У меня возникали похожие проблемы, когда я пытался создать Syntaxhighlighter с помощью RichTextBox. Я узнал, что, когда вы играете arround с ApplyPropertyValue, вы больше не можете просто использовать GetPositionAtOffset. Я считаю, что применение свойств-свойств, по-видимому, изменяет "внутренние позиции" TextTokens внутри документа, и, следовательно, "тормозит" эту функциональность.

Обходной путь:

Каждый раз, когда вам нужно работать с GetPositionAtOffset первым вызовом ClearAllProperties в полном текстовом поле документа, а затем повторно применить все свои свойства с помощью ApplyPropertyValue, но thistime справа налево. (справа означает наивысшее смещение)

Я не знаю, применяли ли вы какие-либо свойства PropertyValues ​​для выделения выделения, поэтому вам может потребоваться больше думать.

Вот как выглядел мой код, когда он вызвал проблему:

    private void _highlightTokens(FlowDocument document)
    {
        TextRange fullRange = new TextRange(document.ContentStart, document.ContentEnd);
        foreach (Token token in _tokenizer.GetTokens(fullRange.Text))
        {
            TextPointer start = fullRange.Start.GetPositionAtOffset(token.Position);
            TextPointer end = start.GetPositionAtOffset(token.Length);

            TextRange range = new TextRange(start, end);
            range.ApplyPropertyValue(TextElement.ForegroundProperty, _getTokenColor(token));
        }
    }

И я исправил это следующим образом:

    private void _highlightTokens(FlowDocument document)
    {
        TextRange fullRange = new TextRange(document.ContentStart, document.ContentEnd);
        fullRange.ClearAllProperties(); // NOTICE: first remove allProperties.
        foreach (Token token in _tokenizer.GetTokens(fullRange.Text).Reverse()) // NOTICE: Reverse() to make the "right to left" work
        {
            TextPointer start = fullRange.Start.GetPositionAtOffset(token.Position);
            TextPointer end = start.GetPositionAtOffset(token.Length);

            TextRange range = new TextRange(start, end);
            range.ApplyPropertyValue(TextElement.ForegroundProperty, _getTokenColor(token));
        }
    }

Ответ 3

Blockquote вы можете получить текст между пробелами.....

частная строка RichWordOver (RichTextBox rch, int x, int y)       {

        int pos = rch.GetCharIndexFromPosition(new Point(x, y));
        if (pos <= 0) return "";


        string txt = rch.Text;

        int start_pos;
        for (start_pos = pos; start_pos >= 0; start_pos--)
        {

            char ch = txt[start_pos];
            if (!char.IsLetterOrDigit(ch) && !(ch=='_')) break;
        }
        start_pos++;
        int end_pos;
        for (end_pos = pos; end_pos < txt.Length; end_pos++)
        {
            char ch = txt[end_pos];
            if (!char.IsLetterOrDigit(ch) && !(ch == '_')) break;
        }
        end_pos--;


        if (start_pos > end_pos) return "";
        return txt.Substring(start_pos, end_pos - start_pos + 1);
    }

private void rchText_MouseClick (отправитель объекта, MouseEventArgs e)       {           MessageBox.Show(RichWordOver (rchText, e.X, e.Y));       }