简体   繁体   中英

Set caret at an index in RichTextBox WPF

I am trying to set the position of caret in richtextbox based on index position of a word. Even though I am able to change the caret position, the caret does not move to the correct location.

Here is my sample code:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        RTB_Main.Document.Blocks.Clear();
        for (int i = 0; i < 10; i++)
        {
            Paragraph para = new Paragraph(new Run(i + ""));
            RTB_Main.Document.Blocks.Add(para);
        }
        TextRange richText = new TextRange(RTB_Main.Document.ContentStart, RTB_Main.Document.ContentEnd);
        string searchText = tb_Search.Text; // 1 to 9

        int position = Regex.Match(richText.Text, searchText).Index;

        RTB_Main.CaretPosition = RTB_Main.Document.ContentStart;
        RTB_Main.CaretPosition = RTB_Main.CaretPosition.GetPositionAtOffset(position);
        RTB_Main.Focus();
    }

What is wrong with this approach? Also, Please let me know if there is a better way to set the caret position to an index?

The problem in my case was caused by new line characters \\r\\n . I just replaced these with another characters and it worked for me. Note that I am replacing them with not 2 characters but 4.

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        RTB_Main.Document.Blocks.Clear();
        for (int i = 0; i < 10; i++)
        {
            Paragraph para = new Paragraph(new Run(i + ""));
            RTB_Main.Document.Blocks.Add(para);
        }
        TextRange richText = new TextRange(RTB_Main.Document.ContentStart, RTB_Main.Document.ContentEnd);
        string searchText = tb_Search.Text; // 1 to 9

        string tmpStr = richText.Text.Replace("\r\n", "....");

        int position = Regex.Match(tmpStr, searchText).Index;
        RTB_Main.CaretPosition = RTB_Main.Document.ContentStart;
        RTB_Main.CaretPosition = RTB_Main.CaretPosition.GetPositionAtOffset(position);
        RTB_Main.Focus();
    }

AsMaciek noted, there are invisible formatting items that affects the count. My code adds a feedback loop because we are able to ask what the true caret position is. It feels hacky but I could not find anything better.

public static void SetCaretPositionOfRichTextBoxToCharIndex(
    System.Windows.Controls.RichTextBox box, int charIndex)
{
    // RichTextBox contains many formattings, and they, although invisible, count
    // when setting CaretPosition. Calling GetPositionAtOffset with charIndex from
    // DocumentStart can be less than the necessary CaretPosition. This code
    // therefore has a feedback loop to see how much more offset is necessary.

    box.CaretPosition = box.CaretPosition.DocumentStart;
    int attemptedCharIndex = 0;
    int fixerInc = 0;
    while (attemptedCharIndex < charIndex)
    {
        box.CaretPosition = box.CaretPosition.GetPositionAtOffset(charIndex - attemptedCharIndex + fixerInc);
        int temp = new TextRange(box.Document.ContentStart, box.CaretPosition).Text.Length;
        if (attemptedCharIndex == temp)
        {
            fixerInc++;
        }
        else
        {
            fixerInc = 0
        }
        attemptedCharIndex = temp;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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