繁体   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