簡體   English   中英

WPF RichTextBox 將插入符號定位到具有給定索引的可見字符

[英]WPF RichTextBox position caret to visible character with given index

我一直在 WPF 中尋找一種快速方法來以編程方式將光標設置為指定的可見符號索引。

問題是,僅僅通過使用Document.ContentStart.GetPositionAtOffset(cursorIndex, LogicalDirection.Forward)我沒有得到想要的結果,因為這個方法也計算不可見的符號 - 例如Run開始和Run結束符號。 文檔中幾乎總是有一些分界符號,所以這總是以光標位於所需位置之前結束。

那么,僅通過可見符號將插入符定位到指定索引的快速、簡單和優雅的方法是什么?

我想出了以下解決方案:

public virtual void SetCursorIndex(Int32 cursorIndex)
{
    // If the specified index is less than or equal to 0, then we simply
    // position the caret to the start of the document.
    if (cursorIndex <= 0)
    {
        CaretPosition = Document.ContentStart;
        return;
    }

    // If the specified index is greater than or equal to the total length, we simply
    // position the caret to the end of the document.
    String fullText = new TextRange(Document.ContentStart, Document.ContentEnd).Text;
    Int32 totalTextLength = fullText.Length;
    if (cursorIndex >= totalTextLength)
    {
        CaretPosition = Document.ContentEnd;
        return;
    }

    // (*)
    TextPointer endPtr = Document.ContentStart
        .GetPositionAtOffset(cursorIndex, LogicalDirection.Forward);
    TextRange range = new TextRange(Document.ContentStart, endPtr);
    Int32 diff = cursorIndex - range.Text.Length;
    while (diff != 0)
    {
        endPtr = endPtr.GetPositionAtOffset(diff, LogicalDirection.Forward);
        range = new TextRange(Document.ContentStart, endPtr);
        diff = cursorIndex - range.Text.Length;

        // Overindexing, in this case we went over the document's length so we
        // position the caret to the end of the document as a safety measure.
        if (diff < 0)
        {
            endPtr = Document.ContentEnd;
            break;
        }
    }

    CaretPosition = endPtr;
}

// (*)之前的部分是不言自明的。 從那里,我們執行以下操作:

  • 我們使用內置機制在cursorIndex邏輯位置(相對於文檔的開頭)獲取文本指針 - 同樣,這包括不可見的符號。 但是如果是這樣,我們不能超過所需的可見字符索引,只能在它之前。 如果它不包含任何不可見的符號,則此方法為我們提供了一個TextPointer我們想要的位置的TextPointer
  • 我們創建了一個TextRange對象,它以文檔開頭和TextPointer創建的TextPointer為界。
  • 我們在TextRange對象中計算cursorIndex和文本Length的差值。 這是我們迭代推進指針直到差異為 0 的量。這是一個簡單的啟發式方法,比迭代推進它快一點點。它基於這樣一個事實,如果TextRange對象包含任何不可見的符號,則顯示的符號的數量永遠不會比位置,我們必須推進我們的數量更大endPtr TextPointer所以我們做的只是這-我們提前endPtr通過的差異cursorIndexrange.Length 如果在所需位置和endPtr指向的當前位置之間有任何不可見的符號,那么我們仍然不會完全到達所需位置 - 這就是為什么我們在while endPtr測試中對endPtr進行推進,以測試長度的差異rangecursorIndex包含的文本為 0。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM