How to "restore" Caret position in Wpf RichTextBox?

After setting my RichTextBox to line T, the Caret position in the RichTextBox is "lost" (it goes to the beginning). Here's what I do to try and "recover" it after it's "lost":

public static int GetCaretIndex(RichTextBox C)
{
    return new TextRange(C.Document.ContentStart, C.CaretPosition).Text.Length;
}
...
int CaretIndex = GetCaretIndex(C); // Get the Caret position before setting the text of the RichTextBox
new TextRange(C.Document.ContentStart, C.Document.ContentEnd).Text = T; // Set the text of the RichTextBox
C.CaretPosition = C.Document.ContentStart.GetPositionAtOffset(CaretIndex, LogicalDirection.Forward); // Set the Caret Position based on the "Caret Index" variable

      

This code, however, does not work. The "restored" Carriage is in a different position than the "original" (always behind the "original" for some reason).

"Saving" RichTextBox CaretPosition as TextPointer doesn't work either.

Can anyone provide me with an alternative way to "repair" Caret, or a way to fix the code above?

+3


source to share


2 answers


Seems to work (for me): C.CaretPosition = C.Document.ContentStart; C.CaretPosition = C.CaretPosition.GetPositionAtOffset(CaretIndex, LogicalDirection.Forward);



(By the way, I hate RichTextBox.)

+2


source


I recently dealt with a similar problem and there is my solution. In my case, I am creating a new RichTextBox.Document content, and when I do this, I want to preserve the caret position.

My idea was that the carriage offset functions are offset thanks to the data structures used for the textual representation (Paragraphs, Runs, ...) that are also calculated for the position offset somehow.

TextRange is a good approach to get the exact caret position in text. The problem lies in its recovery. But it becomes easier for me when I know what components my document is built from. In my case, there are only paragraphs and runs.

It remains to look at the structure of the document, find the exact mileage in which the carriage should be, and set the carriage to correct the position of the found run.



code:

// backup caret position in text
int backPosition = 
    new TextRange(RichTextBox.CaretPosition.DocumentStart, RichTextBox.CaretPosition).Text.Length;

// set new content (caret position is lost there)
RichTextBox.Document.Blocks.Clear();
SetNewDocumentContent(RichTextBox.Document);

// find position and run to which place caret
int pos = 0; Run caretRun = null;
foreach (var block in RichTextBox.Document.Blocks)
{
    if (!(block is Paragraph para))
        continue;

    foreach (var inline in para.Inlines){
    {
        if (!(inline is Run run))
            continue;

        // find run to which place caret
        if (caretRun == null && backPosition > 0)
        {
            pos += run.Text.Length;
            if (pos >= backPosition){
                 caretRun = run;
                 break;
            }
        }
    }

    if (caretRun!=null)
        break;
}

// restore caret position
if (caretRun != null)
    RichTextBox.CaretPosition = 
        caretRun.ContentEnd.GetPositionAtOffset(backPosition - pos, LogicalDirection.Forward);

      

The code is not verified. I put it together from different parts of my application. Let me know if you find any problem.

0


source







All Articles