无法以编程方式获取和设置RichTextBox.CaretPosition

问题描述

我为此进行了几次尝试,但到目前为止没有任何效果

这是普通TextBox功能(这就像一种魅力,但是我需要做一些格式化工作,所以我也需要它才能用于RichTextBox):

//this works:
//Save the actual CaretIndex for later
safeActualCaretPositionInTextBox = txtFormulaString.CaretIndex;
//Insert the (user-)chosen text by another control
txtFormulaString.Text = txtFormulaString.Text.Insert(txtFormulaString.CaretIndex,function.PlainFunction);
//set focus back to TextBox
txtFormulaString.Focus();
//set CaretIndex at needed position (as I insert some formula (i. e. COS()) I need the CaretIndex n position(s) to the left)
txtFormulaString.CaretIndex = safeActualCaretPositionInTextBox + function.PlainFunction.Length;
txtFormulaString.CaretIndex -= function.Caretoffset;
txtFormulaString.SelectionLength = 0;

我已经尝试过这个(RichTextBox.CaretPosition Property),目前拥有这个功能

safeActualCaretPositionInRichTextBox = rtbFormulaString.CaretPosition.GetInsertionPosition(LogicalDirection.Forward);
rtbFormulaString.CaretPosition.GetInsertionPosition(LogicalDirection.Forward).InsertTextInRun(function.PlainFunction);
rtbFormulaString.CaretPosition.GetPositionAtOffset(-function.Caretoffset);
rtbFormulaString.Focus();
rtbFormulaString.CaretPosition = safeActualCaretPositionInRichTextBox;

插入似乎有效,但是我无法将插入符号设置在正确的位置。它始终始于文本的开头。 我做错了什么或我想念什么?

编辑: 当我在项目中使用MVVM时,我在viewmodel中有一个属性,该属性需要在每次更改文本后进行更新(使用了RichTextBox_TextChanged事件):

vm.FormulaString = new TextRange(rtbFormulaString.Document.ContentStart,rtbFormulaString.Document.ContentEnd).Text;

当我删除此行时,它有时会起作用(我不知道为什么或怎么做,我也不知道为什么它会那样运行)。

解决方法

要使插入符号移动到刚刚以编程方式添加的文本的末尾,可以使用以下代码:

TextRange newText = new TextRange(yourRichTextBox.CaretPosition,yourRickTextBox.CaretPosition);
newText.Text = yourString;
yourRichTextBox.CaretPosition = newText.End;

很容易理解:拾取插入符的当前位置,在其中插入一些文字,然后将插入符移动到其末尾

编辑:

要在插入之前保存位置并获取新文本添加的偏移量,可以使用如下方法:

public static uint GetDistanceUntil(this TextPointer start,TextPointer end)
{
    uint ret = 0;
    TextPointer currentPosition = start;
    while (currentPosition.CompareTo(end) != 0)
    {
        // if currentPosition becomes null,you passed through the whole document that contains start and didn't find end 
        // (most likely because start and end aren't in the same document or because start was after end)
        currentPosition = currentPosition.GetPositionAtOffset(1,LogicalDirection.Forward); 
        ret++;
    }
    return ret;
}

以数字的形式获取您的carret的当前位置:yourRichTextBox.ContentStart.GetDistanceUntil(yourRichTextBox.CaretPosition);

并获取文本的“长度”:newText.Start.GetDistanceUntil(newText.End);

添加完文本后,您可以通过使用执行“转换”的方法来获得TextPointer插入符号:

public static TextPointer MoveTo(this TextPointer start,uint distance)
{
    TextPointer ret = start;
    while (distance > 0)
    {
        // if ret becomes null,you passed through the whole document that contains start and didn't move enough yet according to given distance
        ret = ret.GetPositionAtOffset(1,LogicalDirection.Forward); 
        distance--;
    }
    return ret;
}

并将CaretPosition中的RichTextBox设置为yourRichTextBox.ContentStart.MoveTo(savedPosition + textLength);

如果您不总是想使用LogicalDirection.Forward

,我很确定您可以同时使用这两种方法