WPF RichTextBox 将插入符号定位到具有给定索引的可见字符

Posted

技术标签:

【中文标题】WPF RichTextBox 将插入符号定位到具有给定索引的可见字符【英文标题】:WPF RichTextBox position caret to visible character with given index 【发布时间】:2016-03-06 12:07:53 【问题描述】:

我一直在 WPF 中寻找一种快速的方法,以编程方式将光标设置为指定的可见符号索引。

问题在于,仅使用 Document.ContentStart.GetPositionAtOffset(cursorIndex, LogicalDirection.Forward) 并没有得到想要的结果,因为此方法也计算不可见符号 - 例如 Run 开始和 Run 结束符号。文档中几乎总是有一些分界符号,所以这总是以光标在所需位置之前结束。

那么,通过仅考虑可见符号,将插入符号定位到指定索引的快速、简单和优雅的方法是什么?

【问题讨论】:

【参考方案1】:

我想出了以下解决方案:

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,它位于我们想要的位置。 我们创建一个TextRange 对象,该对象以文档开头和之前创建的TextPointer 为界。 我们计算cursorIndexTextRange对象中文本的Length的差异。这是我们迭代地推进指针直到差值为 0 的量。这是一种简单的启发式方法,比迭代地推进 1 快一点。它基于这样一个事实:如果 TextRange 对象包含任何不可见的符号,那么可见符号的数量永远不会大于我们必须推进 endPtr TextPointer 的仓位数量,所以我们这样做 - 我们推进 endPtr 的差值是 cursorIndex 和 @987654335 @。如果在所需位置和endPtr 指向的当前位置之间有任何不可见符号,那么我们仍然不会完全到达所需位置 - 这就是我们在while 循环测试中进行endPtr 改进的原因rangecursorIndex所包含的文本长度之差为0。

【讨论】:

以上是关于WPF RichTextBox 将插入符号定位到具有给定索引的可见字符的主要内容,如果未能解决你的问题,请参考以下文章

如何在 RichTextBox 中隐藏插入符号?

WPF RichTextBox 插入换行 移动光标

WPF RichTextBox 插入回车

WPF中RichTextBox的定位问题。如何使光标定位到与指定关键字所在的位置?

RichTextBox C# 设置插入符号位置 winforms

在富文本框中定位列表框