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.