WPF TextBox selectall and show caret at the same time - c#

after a long search on the net, I hope you can help me.
My Problem:
I want to select the complete text in a TextBox
and will show the caret (blinking cursor) after the last character.
Always I have found information about one problem or information to hide the caret.
The separate things are no problems but the combination of it don't work.
// Set the focus to the TextBox
myTextBox.Focus();
// Select the complete text, but hide the caret (blinking cursor)
myTextBox.SelectAll();
// or
// myTextBox.Select(0, myTextBox.Text.Length);
// Set the caret after the last character, but loss the selection from the text
myTextBox.CaretIndex = myTextBox.Text.Length;
So, I see the caret after the last character, but the text is not selected
myTextBox.Focus();
myTextBox.SelectAll();
myTextBox.CaretIndex = myTextBox.Text.Length;
And so, the text is selected, but no caret is shown.
myTextBox.Focus();
myTextBox.CaretIndex = myTextBox.Text.Length;
myTextBox.SelectAll();
And that's the problem: one of them deactivate the another one, but I need these two things at the same time
I using WPF and .Net 4.0
Thanks for helping :-)

The problem is the strong internal connection in the TextBox between CaretIndex and the Selection.
Whenever you modify the selection with Select() or SelectAll(), the TextBox automatically places the CaretIndex at the beginning of the selection. In reverse, the TextBox clears the selection when you manually modify the CaretIndex. You can make this behavior visible, if you register for SelectionChanged in the TextBox and output the current CaretIndex to Console.
This is for a good reason, as Okuma.Scott already mentioned in his comment.
So if your desired behaviour is really required, you probably need to implement your own CustomTextBox.

This worked for me:
TextBox.Text = _Text;
System.Windows.Input.Keyboard.Focus(TextBox);
TextBox.GotFocus += (sender, e) => {
if (_selectAll)
{
//I think Caret can be set here but I didn't try it
TextBox.SelectAll();
}
};

Related

Why is the "RichTextBox.SelectionBackColor" not reverting to default on the new and unselected text, after the SelectionBackColor was changed?

I have a RichTextBox. I'm working on changing the SelectionBackColor only of the selected text.
Then, I have a ToolStripMenuItem(let's call it 'buttonA' for now) which is responsible to change the SelectionBackColor of the selected text. The problem I'm facing is after I click buttonA, the background color of the selected text in the RichTextBox can be successfully done. However, when I add some other characters or text right after the changed background color text, it doesn't use the default background color. Instead, it continues to use the same background color as assigned from buttonA, which I don't want to happen.
At first, I thought that my start index and end index of the selected text was problematic. But, I don't think there's any problems in its codes. Below shows the code example:
SolidBrush textBgCol; //a variable to keep color
this.richTextBox1.Select = this.richTextBox1.SelectionStart, this.richTextBox1.SelectionLength;
this.richTextBox1.SelectionBackColor = Color.FromArgb(textBgCol.Color.A, textBgCol.Color.R, textBgCol.Color.G, textBgCol.Color.B);
One of my efforts was to change the SelectionBackColor to default in the KeyDown event of richTextBox1. However, the background color of the new or successive characters and text were still the same as assigned from buttonA. Below shows the code example:
private void richTextBox1_KeyDown(object sender, KeyEventArgs e)
{
this.richTextBox1.SelectionBackColor = default;
}
I've also tried to refer to this but, I don't think it helps me to solve my case here.
Other than that, just to confirm that my richTextBox1's SelectionStart and SelectionLength were okay, I've even referred to these: ref1, ref2, and ref3.
May I know any other workarounds for this please? Or, were there anything inside my codes that I've missed?
Based on comment by #Jimi:
I just need to change the codes in my richTextBox1's KeyDown event handler to:
if(richTextBox1.SelectionBackColor != richTextBox1.BackColor)
{
richTextBox1.SelectionBackColor = richTextBox1.BackColor;
}
Below shows the demo:
Thanks!

How to implement a "fully viewed" multi-line TextBox?

I am trying to create a form with a multi-line TextBox with the following requirements:
The text in the text box might be short or long.
There is not much space availble.
I want to be sure that the entirety of the text has been seen. I can't be sure that the user has actually read it, but I can at least require that all of it has been seen.
So I'm trying to make a "fully viewed" multi-line TextBox.
This picture should make it clear what I'm trying to do:
If they check the checkbox before they've scrolled through the whole thing, I'll know not to believe them.
I think I need to know:
When the form comes up, was the text that was put into the TextBox short (all visible without scrolling) or long (the vertical scroll bar was shown)?
If the vertical scroll bar is showing, has the user scrolled it all the way to the bottom?
Any ideas about how to achieve this?
The TextBox has no scrolling event but the RichTextBox has. Also it has a method that allows you to get the index of the character closest to a point position.
private readonly Point _lowerRightCorner;
public frmDetectTextBoxScroll()
{
InitializeComponent();
_lowerRightCorner = new Point(richTextBox1.ClientRectangle.Right,
richTextBox1.ClientRectangle.Bottom);
}
private void richTextBox1_VScroll(object sender, EventArgs e)
{
int index = richTextBox1.GetCharIndexFromPosition(_lowerRightCorner);
if (index == richTextBox1.TextLength - 1) {
// Enable your checkbox here
}
}

WPF TextBox, Updating Text Property Resets Cursor Position

In a WPF application, if the Text property of a TextBox control is programmatically updated while the user still has focus on the control (say, with a TextChanged or KeyUp event), is it possible to maintain the position of the user's cursor after the Text property has been updated?
In normal circumstances, if the Text property is updated, and user has focus on the control, the cursor is simply reset back to the start of the TextBox.
Yes, it is possible to maintain the user's cursor position after a value change. Let us examine a scenario where this can be used.
Consider a TextBox control where you only want the user to enter alphanumeric value, and have all other characters removed.
You might have some XAML looking like this:
<TextBox x:Name="myInput" Margin="72,95,0,0" TextChanged="clearInputHandler" />
... and a C# handler, like this:
private void clearInputHandler(object sender, TextChangedEventArgs e)
{
string validInput = Regex.Replace(myInput.Text, "[^A-Za-z0-9]", "");
myInput.Text = validInput;
}
However, this suffers from the problem where the cursor position will be set to the beginning of the input if the Text property is updated.
To correct this issue, use the CaretIndex property, which grabs the location of the user's cursor:
private void clearInputHandler(object sender, TextChangedEventArgs e)
{
int oldIndex = myInput.CaretIndex;
string oldValue = myInput.Text;
string validInput = Regex.Replace(myInput.Text, "[^A-Za-z0-9]", "");
myInput.Text = validInput;
if (!oldValue.Equals(validInput))
{
myInput.CaretIndex = oldIndex - 1;
}
}
A few notes on the above code sample:
Notice how the CaretIndex property is gathered before any changes are made to the Text property. This way we know where the cursor is before anything is changed.
The original value of the TextBox is saved. See #4.
The Text property is set again, before the user's cursor position is changed.
The if statement at the bottom is only run if the regex changes the text it was given. The cursor position, by nature will automatically advance to the next space, as the user types valid input. However, if the user enters an invalid character, the oldIndex registers the next space the cursor should normally go, the regex removes the invalid character, and the if statement is run, and moves back once space, since the invalid character was removed.

How do you prevent a multiline textbox from scrolling when text is added?

I have a multiline TextBox called Console. While running, this textbox is being filled up with some communications data. I use
TextBox.AppendText("txt\r\n");
to add a line to it and that allows me to have it autoscroll down. My problem is I want to be able to not have it autoscroll down. So I thought I would try
TextBox.Text += "text";
But that scrolls you to the beginning of the box. My latest attempt was to use TextBox.SelectionStart to save the position before I wrote and restore it back to that after, but that didn't seem to make a difference and still brings me back to the beginning of the text.
int txtPosition = Console.SelectionStart;
Console.Text += "TextToAdd";
Console.SelectionStart = txtPosition;
Ideally I want to just be able to have the box stay where ever it happens to be and not scroll to the beginning or end of the text.
I think you need to you a richtextbox instead of a generic textbox and this will provide you with the functionality you desire.
Enjoy!
For a WinForms textbox, you may should able to do this:
textBox.SelectionStart = 0;
textBox.ScrollToCaret(); // force current position back to top

How do I scroll a RichTextBox to the bottom?

I need to be able to scroll a RichTextBox to the bottom, even when I am not appending text. I know I can append text, and then use that to set the selection start. However I want to ensure it is at the bottom for visual reasons, so I am not adding any text.
You could try setting the SelectionStart property to the length of the text and then call the ScrollToCaret method.
richTextBox.SelectionStart = richTextBox.Text.Length;
richTextBox.ScrollToCaret();
The RichTextBox will stay scrolled to the end if it has focus and you use AppendText to add the information. If you set HideSelection to false it will keep its selection when it loses focus and stay auto-scrolled.
I designed a Log Viewer GUI that used the method below. It used up to a full core keeping up. Getting rid of this code and setting HideSelection to false got the CPU usage down to 1-2%.
//Don't use this!
richTextBox.AppendText(text);
richTextBox.ScrollToEnd();
In WPF you can use ScrollToEnd:
richTextBox.AppendText(text);
richTextBox.ScrollToEnd();
Code should be written in the rich text box's TextChanged event like :
private void richTextBox_TextChanged(object sender, EventArgs e) {
richTextBox.SelectionStart = richTextBox.Text.Length;
richTextBox.ScrollToCaret();
}

Categories

Resources