简体   繁体   中英

How To Set Caret Position At The End Of Current Line In A RichTextBox

I'm trying to place the caret of a RichTextBox at the end of the current line it's in. The .CaretPosition attribute is a big change from just using the simple .CaretIndex attribute of a regular TextBox .

To tackle this issue, I've made my own User-Control which is just a RichTextBox that has most of the properties/methods a TextBox has, such as .LineCount , .Text , .CaretIndex , etc. I made a CaretIndex { get; set; } CaretIndex { get; set; } CaretIndex { get; set; } property within my User-Control that looks like this:

public int CaretIndex
        {
            get
            {
                TextPointer start = display.Document.ContentStart;
                TextPointer curPosition = display.CaretPosition;
                TextRange range = new TextRange(start, curPosition);
                return range.Text.Length;
            }
            set
            {
                display.CaretPosition = display.Document.ContentStart;
                for (int i = 0; i < value; i++)
                {
                    TextPointer move = display.CaretPosition.GetNextInsertionPosition(LogicalDirection.Forward);
                    if (move != null)
                        display.CaretPosition = move;
                }
            }
        }    

The get method seems to work fine, but set doesn't do what I envision it to accomplish. My goal was to have the caret move logically forward a "value" amount of times - value being how many characters I want to move past - but the result is just abstract caret placement behavior. The caret could either get placed a couple lines down, right below the original line, or all the way to the bottom of the RichTextBox .

All I want is an easy way to move the caret left or right without undefined behavior. Am I approaching my CaretIndex property the wrong way? Do I have a false perception of the CaretPosition property of a RichTextBox ? Any suggestions on what to do?

I made a small wpf app to test your code -

xaml -

<Grid.RowDefinitions>
    <RowDefinition Height="300"/>
    <RowDefinition Height="100"/>
    <RowDefinition Height="100"/>
</Grid.RowDefinitions>

<RichTextBox Grid.Row="0" Name="Rtb" />
<Button Grid.Row="1" Content="Get" Click="Button_Get" />

<Grid Grid.Row="2">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <Button Grid.Column="0" Content="Set" Click="Button_Set" />
    <TextBox Grid.Column="1" Name="DesiredPositionBox" />
</Grid>

c# -

    public MainWindow()
    {
        InitializeComponent();

        Rtb.AppendText("lineoftextlineoftextlineoftextlineoftext");
        Rtb.AppendText(Environment.NewLine);
        Rtb.AppendText("lineoftextlineoftextlineoftextlineoftext");
    }

    private void Button_Get(object sender, RoutedEventArgs e)
    {
        TextPointer start = Rtb.Document.ContentStart;
        TextPointer curPosition = Rtb.CaretPosition;
        TextRange range = new TextRange(start, curPosition);
        Debug.WriteLine("Caret position : " + range.Text.Length);

        Rtb.Focus();
    }

    private void Button_Set(object sender, RoutedEventArgs e)
    {
        int value = int.Parse(DesiredPositionBox.Text);

        Rtb.CaretPosition = Rtb.Document.ContentStart;
        for (int i = 0; i < value; i++)
        {
            TextPointer move = Rtb.CaretPosition.GetNextInsertionPosition(LogicalDirection.Forward);
            if (move != null)
                Rtb.CaretPosition = move;
        }

        Rtb.Focus();
    }

The line Rtb.CaretPosition = Rtb.Document.ContentStart; moves the caret to the start every time, so if you pass in '5' the caret will be moved to the 5th character from the start of the RichTextBox.

Remove Rtb.CaretPosition = Rtb.Document.ContentStart; and the caret will move x positions from where it was.

edit: To also answer how to place the caret at the end of the line, you can use Rtb.CaretPosition.GetTextRunLength(LogicalDirection.Forward) to get the number of characters, counting from the caret, before the first non text symbol ( which line break happens to be ).

So -

        int value = Rtb.CaretPosition.GetTextRunLength(LogicalDirection.Forward);
        TextPointer move = Rtb.CaretPosition.GetPositionAtOffset(value);
        Rtb.CaretPosition = move;

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