简体   繁体   English

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

[英]Unable to get and set the RichTextBox.CaretPosition programmatically

I have tried several attempts for this, but nothing has worked so far.我为此尝试了几次尝试,但到目前为止没有任何效果。

Here is what I have for a normal TextBox (this works like a charm, but as I need to do some formatting I need it to work for the RichTextBox, too):这是我对普通 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;

I have tried this ( RichTextBox.CaretPosition Property ) and currently have this:我试过这个( 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;

The insertion seems to work but I can't set the caret to the right position.插入似乎有效,但我无法将插入符号设置到正确的位置。 It always starts at the beginning of the text.它总是从文本的开头开始。 What do I do wrong or what am I missing?我做错了什么或我错过了什么?

EDIT: As I use MVVM in my project, I have a property in my ViewModel which needs to be updated after every text change (RichTextBox_TextChanged event is used):编辑:当我在我的项目中使用 MVVM 时,我的 ViewModel 中有一个属性需要在每次文本更改后更新(使用 RichTextBox_TextChanged 事件):

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

When I delete this line, it works sometimes (I don't know why or how and I don't understand why it behaves like that).当我删除这一行时,它有时会起作用(我不知道为什么或如何,我不明白它为什么会这样)。

To make the caret move to the end of the text you just added programatically you can use the following code :要使插入符号移动到您刚刚以编程方式添加的文本的末尾,您可以使用以下代码:

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

It's pretty clear to understand : pickup the current position of your caret, write some text at it and then move the caret to the end of it很容易理解:拾取插入符号的当前位置,在上面写一些文本,然后将插入符号移动到它的末尾

EDIT :编辑 :

To save the position before inserting and to get the offset added by your new text you can use a method like this :要在插入之前保存位置并获取新文本添加的偏移量,您可以使用如下方法:

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;
}

To obtain the current position of your carret as a number : yourRichTextBox.ContentStart.GetDistanceUntil(yourRichTextBox.CaretPosition);以数字形式获取当前位置: yourRichTextBox.ContentStart.GetDistanceUntil(yourRichTextBox.CaretPosition);

And to get the "length" of your text : newText.Start.GetDistanceUntil(newText.End);并获得文本的“长度”: newText.Start.GetDistanceUntil(newText.End);

Once you're done adding the text you can obtain the TextPointer where your caret should be by using the method that does the "conversion" the other way :完成添加文本后,您可以通过使用以另一种方式进行“转换”的方法来获取插入符号所在的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;
}

And set the CaretPosition of your RichTextBox to yourRichTextBox.ContentStart.MoveTo(savedPosition + textLength);并将RichTextBoxCaretPosition设置为yourRichTextBox.ContentStart.MoveTo(savedPosition + textLength);

I'm pretty sure you can adapt both methods if you don't always want to use LogicalDirection.Forward如果您不总是想使用LogicalDirection.Forward我很确定您可以采用这两种方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM