Keep selection when clicking into textbox - c#

I need to have the text in a TextBox become selected when a user clicks into the box. If the text is already selected, it needs to be a regular cursor. So on the click event of all the textboxes I have this code:
TextBox t = (TextBox)sender;
bool alreadyselected = t.SelectedText == t.Text;
if (!alreadyselected) t.SelectAll();
the problem is, by the time the click event is reached, t.SelectedText is empty
so the full text always becomes selected even when clicking multiple times
I would appreciate a solution that can be for all the textboxes at once if possible

You're correct, the default Click for the TextBox is changing the position of the caret and thus clearing any selected text. But you can restore it.
First add 2 int vars to store the selection Start and Length and initialize Start as -1 to signal not set:
private int SelectedStart = -1;
private int SelectedLength = 0;
then make a handler for the TextBox's Leave event and save the Start and Length for the currently selected text when we lose focus.
private void textBox1_Leave (object sender, EventArgs e)
{
SelectedStart = textBox1.SelectionStart;
SelectedLength = textBox1.SelectionLength;
}
Finally, make a handler for the TextBox's Click event and, if we previously saved the Start and Length, restore them to the TextBox and then set Start to -1 to signal not set again (this allows for normal click behavior within textbox when it is focused).
private void textBox1_Click (object sender, EventArgs e)
{
if (SelectedStart != -1) {
textBox1.SelectionStart = SelectedStart;
textBox1.SelectionLength = SelectedLength;
SelectedStart = -1;
}
}

Use the Control.Tag property to set a bool flag to select or deselect the TextBox text:
private void TextBox_Click(object sender, EventArgs e)
{
TextBox txtBox = (TextBox)sender;
txtBox.SelectionStart = 0;
// First click will select the text
if (txtBox.Tag == null)
{
txtBox.Tag = true;
txtBox.SelectionLength = txtBox.Text.Length;
}
// Second click will deselect the text
else
{
txtBox.Tag = null;
txtBox.SelectionLength = 0;
}
}

Related

How to highlight entire TextBox on triple click?

When there are spaces between the text in the Input TextBox, my triple click only highlights up to the next space instead of the whole TextBox. Help?
Subscribe to the DoubleClick event:
private void textBox1_DoubleClick(object sender, EventArgs e)
{
textBox1.SelectionStart = 0; // set the selection start index to the beginning
textBox1.SelectionLength = textBox1.Text.Length; // set the selection length to the length of the text
}
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.doubleclick?view=windowsdesktop-7.0

How to unselect line when clicking outside of any text

I have a feature that selects the line on which user clicks.
private void richTextBox1_MouseClick(object sender, MouseEventArgs e)
{
if(richTextBox1.Lines.Length!=0)
{
int firstcharindex = richTextBox1.GetFirstCharIndexOfCurrentLine();
int currentline = richTextBox1.GetLineFromCharIndex(firstcharindex);
string currentlinetext = richTextBox1.Lines[currentline];
richTextBox1.Select(firstcharindex, currentlinetext.Length);
}
}
I want to achieve that when user clicks elsewhere (not on any line of text but still inside the textbox or anywhere else) the text will become unselected.
I tried using the GetFirstCharIndexOfCurrentLine() method of RichTextBox but if i click outside of any text the previous value is remembered.

C# WinForms contextmenu focus issue when textbox is added

In a C# WinForms application I need to create a ContextMenuStrip with dropdown and textbox:
private System.Windows.Forms.ContextMenuStrip ct1;
private void button_Click(object sender, EventArgs e)
{
var header = new ToolStripMenuItem("Header");
header.Enabled = false;
var options = new ToolStripMenuItem("Options");
for (int i = 0; i < 5; i++)
{
var checkoption = new ToolStripMenuItem("Check Me " + i + "!");
checkoption.CheckOnClick = true;
options.DropDownItems.Add(checkoption);
}
var txt = new ToolStripTextBox();
txt.Text = "changeme";
options.DropDownItems.Add(txt);
options.DropDown.Closing += DropDown_Closing;
ct1.Items.Clear();
ct1.Items.Add(header);
ct1.Items.Add(options);
ct1.Show(this, button.Left, button.Top);
}
private void DropDown_Closing(object sender, ToolStripDropDownClosingEventArgs e)
{
e.Cancel = (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked);
}
Now, e.Cancel will prevent closing the dropdown if the reason is ItemClicked, so I can select more items without having to open the menu again:
Please note that "changeme" is a ToolStripTextBox!
Once I focus it (click on it), I can edit the text inside:
After finish editing the textbox, I still can change the checkbox items, but there is no focus indicator:
How can I get back the focus indicator just as shown on the first picure?
Note: if I move the mouse onto "Header", the dropdown will close, and then moving it back to "Options", will reopen the dropdown and then the focus indicator is good again:
How can I do this without closing and reopening the dropdown?
I have tried Select() for the options item, but it did not help, neither Invalidate() on ct1.
Just have found it:
First needs to add a click handler on the dropdown:
options.DropDown.Click += DropDown_Click;
Then in the click handler it needs to be focused:
private void DropDown_Click(object sender, EventArgs e)
{
var dropdown = (ToolStripDropDown)sender;
dropdown.Focus();
}

Switching to a tab in TabControl using code

I have a tabcontrol in my application that has several tabs in it.
I want to automatically switch to another tab when the "Next" button is pressed.
I cannot figure out how to change which tab is visible programmatically.
private void Next_Click(object sender, EventArgs e)
{
// Change to the next tab
tabControl1.???;
}
Use the TabControl.SelectedTab property. MSDN.
tabControl1.SelectedTab = anotherTab;
But you can also use the TabControl.SelectedIndex property. MSDN.
try
{
tabControl1.SelectedIndex += 1;
}
catch
{
//This prevents the ArgumentOutOfRangeException.
}
For this particular scenario you can use SelectedIndex property of the TabControl. This gives you an integer representing the index of the currently selected tab. Likewise you can set a tab as selected by setting an integer value to this property.
private void btnNext_Click(object sender, EventArgs e)
{
int currentTabIndex = tabControl1.SelectedIndex;
currentTabIndex++;
if (currentTabIndex < tabControl1.TabCount)
{
tabControl1.SelectedIndex = currentTabIndex;
}
else
{
btnNext.Enabled=false;
}
}

How to determine whether TextChanged was triggered by keyboard in C#?

I have a method
private void textBoxPilot_TextChanged(object sender, TextChangedEventArgs e)
{ ... }
where the textbox in question takes a search string from the user and populates a ListBox with the results on every keystroke.
Subsequently, when an item is picked from the ListBox, I would like the choice reflected in the same Textbox. However, I don't want to trigger the search mechanism, which would cause the Listbox to forget its selection.
How can I determine whether the TextChanged event was triggered by the user (via they keyboard or maybe copy/paste) or by another method using textBoxPilot.Text = "Pilot name";?
Thanks.
bit of a hack, but....
public class MyForm : Form
{
private bool _ignoreTextChanged;
private void listView1_SelectionChanged( object sender, EventArgs e )
{
_ingnoreTextChanged = true;
textBoxPilot.Text = listView1.SelectedValue.ToString(); // or whatever
}
private void textBoxPilot_TextChanged( object sender, TextChangedEventArgs e )
{
if( _ignoreTextChanged )
{
_ignoreTextChanged = false;
return;
}
// Do what you would normally do.
}
}
A disabled control will not fire a event. So two options are either always disable update the text then re-enable or create a derived class wrapper (using this method you could still do data binding)
class myClass : TextBox
{
public virtual string TextWithoutEvents
{
get
{
return base.Text;
}
set
{
bool oldState = Enabled;
Enabled = false;
base.Text = value;
Enabled = oldState;
}
}
}
If the user selects "Pilot name" from the list, you set the text box to "Pilot name". This will cause the list box to select "Pilot name". So the selection should be kept. You just have to break the recursion.
In my scenario where user has to type in text to trigger auto-complete and we didn't want a re-trigger when the auto-complete changes the text again, I used the text lengths. This won't work if user copy/pastes and therefore adds more than 1 character at a time with the keyboard.
private void HandleTextChanged(object sender, TextChangedEventArgs e){
var oldText = e.OldTextValue;
var newText = e.NewTextValue;
// Assuming text changed from keyboard is always 1 character longer,
// ignore this text changed event if new text > 1 character longer.
if (newText.Length > oldText.Length + 1) {
return;
}
...
}
In your scenario, if you always know the values you want to skip, then you could check for them instead:
if (newText == "Pilot name") {
return;
}
or
if (myListOfNamesToIgnore.Contains(newText)) {
return;
}

Categories