9

テキストを入力してから、テキスト全体を解析して処理を行う WPF RichTextBox があります。この解析中に、各単語の開始位置と終了位置の絶対文字位置がわかりました。

これらの文字位置を使用して、特定の単語に書式を適用したいと考えています。しかし、FlowDocument が TextPointer インスタンスを使用してドキュメント内の位置をマークしていることを発見しました。

開始ポインターと終了ポインターを使用して TextRange を作成できることがわかりました。TextRange を取得したら、その中のテキストに書式を簡単に適用できます。GetPositionAtOffset を使用して文字オフセットの TextPointer を取得していますが、選択したテキストが予想とは少し異なる位置にあるため、オフセットが私のものと異なると思われます。

私の質問は、絶対文字位置を TextPointer に正確に変換するにはどうすればよいですか?

4

3 に答える 3

7

私もこの問題を抱えており、最終的に次の RichTextBox 拡張メソッドになりました。私のコンテキストでは、問題なく動作します。

/// <summary>
/// Gets the text pointer at the given character offset.
/// Each line break will count as 2 chars.
/// </summary>
/// <param name="richTextBox">The rich text box.</param>
/// <param name="offset">The offset.</param>
/// <returns>The TextPointer at the given character offset</returns>
public static TextPointer GetTextPointerAtOffset(this RichTextBox richTextBox, int offset)
{
    var navigator = richTextBox.Document.ContentStart;
    int cnt = 0;

    while (navigator.CompareTo(richTextBox.Document.ContentEnd) < 0)
    {
        switch (navigator.GetPointerContext(LogicalDirection.Forward))
        {
            case TextPointerContext.ElementStart:
                break;
            case TextPointerContext.ElementEnd:
                if (navigator.GetAdjacentElement(LogicalDirection.Forward) is Paragraph)
                    cnt += 2;
                break;
            case TextPointerContext.EmbeddedElement:
                // TODO: Find out what to do here?
                cnt++;
                break;
            case TextPointerContext.Text:
                int runLength = navigator.GetTextRunLength(LogicalDirection.Forward);

                if (runLength > 0 && runLength + cnt < offset)
                {
                    cnt += runLength;
                    navigator = navigator.GetPositionAtOffset(runLength);
                    if (cnt > offset)
                        break;
                    continue;
                }
                cnt++;
                break;
        }

        if (cnt > offset)
            break;

        navigator = navigator.GetPositionAtOffset(1, LogicalDirection.Forward);

    } // End while.

    return navigator;
}
于 2014-10-11T17:02:51.737 に答える
6

文字の絶対位置を TextPosition インスタンスに変換する信頼できる方法が見つかりませんでした。

私の別の解決策は、元の解析を変更して、RichTextBox のテキスト全体をキャプチャするのではなく、個々の実行で機能するようにすることでした。特定の Run インスタンスに相対的なキャラクターの位置を操作することは、私にとって信頼できるものであることが証明されました。自分の考え方を WPF の考え方に近づけることが役に立ったと思います。

FlowDocument で実行をナビゲートするために、次のアプローチを採用しました ( http://blogs.msdn.com/prajakta/archive/2006/10/12/customize-richtextbox-to-allow-only-plain-text-input. aspx ):

// Get starting pointer
TextPointer navigator = flowDocument.ContentStart;

// While we are not at end of document
while (navigator.CompareTo(flowDocument.ContentEnd) < 0)
{
    // Get text pointer context
    TextPointerContext context = navigator.GetPointerContext(LogicalDirection.Backward);

    // Get parent as run
    Run run = navigator.Parent as Run;

    // If start of text element within run
    if (context == TextPointerContext.ElementStart && run != null)
    {
        // Get text of run
        string runText = run.Text;

        // ToDo: Parse run text
    }

    // Get next text pointer
    navigator = navigator.GetNextContextPosition(LogicalDirection.Forward);
}
于 2010-04-05T09:33:07.407 に答える
1

私はまったく同様の問題を抱えていました.RichTextBoxには「改行文字-\r\n」がカウントされないため、バグがあることがわかりました.行番号が増えると、オフセットが行ごとに間違っていることがわかります.行番号をオフセットからオフセットすることで問題を解決しました。

于 2010-04-02T09:24:19.973 に答える