How can I sync two TextBox control's Text properties? - c#

If I have two text boxes on a form, how can I make it so that their text properties are perfectly synced? Similar to what would happen if they both processed the same KeyDown event.

I would do it this way:
textBox1.TextChanged += (s, _) =>
{
if (!textBox2.Focused && textBox1.Text != textBox2.Text)
{
textBox2.Text = textBox1.Text;
}
};
textBox2.TextChanged += (s, _) =>
{
if (!textBox1.Focused && textBox2.Text != textBox1.Text)
{
textBox1.Text = textBox2.Text;
}
};
Basically I'm responding to the TextChanged even on each text box, but making sure that the target text box doesn't have focus and that the text actually has changed. This prevents infinite back-and-forth loop trying to update the text and it makes sure that the current insertion point isn't changed by the text being overwritten.

I would say that you partially answered your own question, have them both assigned to the same TextChanged EventHandler check which textbox has changed then update the Text property of the other one, something like this.
private void textBox_TextChanged(object sender, EventArgs e)
{
if (((TextBox)sender).Equals(textBox1))
textBox2.Text = ((TextBox)sender).Text;
else
textBox1.Text = ((TextBox)sender).Text;
}
Modified Code to Keep Carat Position Synced between the two TextBox's , see if this is what you are wanting.
private void textBox_TextChanged(object sender, EventArgs e)
{
TextBox tb = (TextBox)sender;
if (tb.Equals(textBox1))
{
if (textBox2.Text != tb.Text)
{
textBox2.Text = tb.Text;
textBox2.SelectionStart = tb.SelectionStart;
textBox2.Focus();
}
}
else
{
if (textBox1.Text != tb.Text)
{
textBox1.Text = tb.Text;
textBox1.SelectionStart = tb.SelectionStart;
textBox1.Focus();
}
}
}

I would simply do as follows:
bool flag1, flag2;
private void t1_TextChanged(object sender, EventArgs e)
{
if (flag2) return;
flag1 = true;
t2.Text = t1.Text;
flag1 = false;
}
private void t2_TextChanged(object sender, EventArgs e)
{
if (flag1) return;
flag2 = true;
t1.Text = t2.Text;
flag2 = false;
}

Related

C# trigger event for datagridview cell text changed [duplicate]

i am making a windows form application in which i used a datagridview.
i want that when i write something in textbox in datagridview,than a messagebox appears containing the string i wrote..
ican't get my text in textchanged event..
all thing must be fired in textchanged event..
here is my code:-
void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (dataGridView1.CurrentCell.ColumnIndex == 1)
{
TextBox tb = (TextBox)e.Control;
tb.TextChanged += new EventHandler(tb_TextChanged);
}
}
void tb_TextChanged(object sender, EventArgs e)
{
//listBox1.Visible = true;
//string firstChar = "";
//this.listBox1.Items.Clear();
//if (dataGridView1.CurrentCell.ColumnIndex == 1)
{
string str = dataGridView1.CurrentRow.Cells["Column2"].Value.ToString();
if (str != "")
{
MessageBox.Show(str);
}
}
void tb_TextChanged(object sender, EventArgs e)
{
var enteredText = (sender as TextBox).Text
...
}
Showing MessageBox in TextChanged will be very annoying.
Instead you could try it in DataGridView.CellValidated event which is fired after validation of the cell is completed.
Sample code:
dataGridView1.CellValidated += new DataGridViewCellEventHandler(dataGridView1_CellValidated);
void dataGridView1_CellValidated(object sender, DataGridViewCellEventArgs e)
{
if (dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value != null)
{
MessageBox.Show(dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString());
}
}

Canceling textboxes if I type in other textbox

I got few textboxes in my form. I would like to type in one textbox and the other textboxes will be automatically canceled (Canceled so the user wont be able to type anymore in the other textboxes).
If the user delete the word he typed in the textbox (or in other words: if the textbox is empty) all other textboxes will be enabled again.
Here is what I got so far:
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (textBox1.Text.Trim().Length > 0)
{
// Disable other textboxes (I have no idea how can I do that).
}
else if (textBox1.Text.Trim().Length == 0)
{
// Enable other textboxes
}
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (textBox1.Text.Trim().Length > 0)
{
// Keep this comboBox enabled while typing in textBox1.
}
}
How can I disable other textboxes while typing in priticillar textbox? (also keeping comboBox enabled).
DO NOTICE: I would like to do the same on textBox2 (when I type in textBox2, textbox 1 and 3 will be disabled) and textBox3.
You don't need a condition on your 'else if', just 'else' will do, as if the length is more than 0, the only other possibility is 0. Also you can use the sender instead of hardcoding the control name.
Then set the Enabled property for the textbox's you want disabled. You can loop through all the textbox's on the form, excluding the one you are typing into, or just manually list them. SImpler is putting the textbox's in a groupbox, then if you disable the groupbox it will disable the controls with in it.
private void textBox1_TextChanged(object sender, EventArgs e)
{
var senderTextBox = (TextBox)sender;
var textBoxesEnabled = senderTextBox.Text.Trim().Length == 0;
textBox2.Enabled = textBoxesEnabled;
textBox3.Enabled = textBoxesEnabled;
// OR
groupBox1.Enabled = textBoxesEnabled;
}
REPLY EDIT: You can chain of textbox's, say 4 of them, disable the last 3, then:
void TextBox1TextChanged(object sender, System.EventArgs e)
{
var isTextEmpty = ((TextBox)sender).Text.Trim() == "";
textBox2.Enabled = !isTextEmpty;
}
void TextBox2TextChanged(object sender, System.EventArgs e)
{
var isTextEmpty = ((TextBox)sender).Text.Trim() == "";
textBox1.Enabled = isTextEmpty;
textBox3.Enabled = !isTextEmpty;
}
void TextBox3TextChanged(object sender, System.EventArgs e)
{
var isTextEmpty = ((TextBox)sender).Text.Trim() == "";
textBox2.Enabled = isTextEmpty;
textBox4.Enabled = !isTextEmpty;
}
void TextBox4TextChanged(object sender, System.EventArgs e)
{
var isTextEmpty = ((TextBox)sender).Text.Trim() == "";
textBox3.Enabled = isTextEmpty;
}
But for a large amount of textbox's, another alternative is having multiple textbox share the same TextChanged event. You need to click on each TextBox control, go into the Events list and manually select the method for TextChanged. Here is the method:
private void TextBoxGroup_TextChanged(object sender, EventArgs e)
{
var groupOrder = new List<TextBox>() { textBox1, textBox2, textBox3, textBox4 };
var senderTextBox = (TextBox)sender;
var senderIndex = groupOrder.IndexOf(senderTextBox);
var isTextEmpty = senderTextBox.Text.Trim() == "";
if (senderIndex != 0) groupOrder[senderIndex - 1].Enabled = isTextEmpty;
if (senderIndex != groupOrder.Count - 1) groupOrder[senderIndex + 1].Enabled = !isTextEmpty;
}
Use Controls collection and some LINQ:
if (textBox1.Text.Trim().Length > 0)
{
var textboxes = this.Controls.OfType<TextBox>().Where(x => x.Name != "textBox1");
foreach(var tBox in textboxes)
tBox.Enabled = false;
}

Passing params to EventMethod in Visual C#

I have these two methods and I have to use them to modify the selected item in a ListBox and after editing it in the same txtBox I use for filling up the ListBox to get it back and replace It with the old one.
private void txtBox_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
List.Items.Add(Label.Content);
Label.Content = "";
txtBox.Text = "";
}
}
private void ButtonModify_Click(object sender, RoutedEventArgs e)
{
int index = List.SelectedIndex;
object item = List.SelectedItem;
txtBox.Text = (string)item;
txtBox_KeyUp(????????);
}
My intuition says I have to call the EventMethod I've use to fill the ListBox, but there are some parameter which I can't remove cause I need them in the txtBody_KeyUp(). So my question is what I have to write as an arguments to work or is there some other way for doing this?
You Can Use Below Code.
Text Box PreviewKeyDown Event
private int _tmpIndex = -1;
private void TextBox_OnPreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key != Key.Enter || _tmpIndex == -1) return;
ListBox1.Items[_tmpIndex] = TextBox1.Text;
TextBox1.Text = "";
_tmpIndex = -1;
}
ListBox MouseDoubleClick Event
private void ListBox_OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (ListBox1.SelectedIndex <= 0) return;
TextBox1.Text = ListBox1.SelectedItem.ToString();
_tmpIndex = ListBox1.SelectedIndex;
}
Have Fun

Appending & removing text from a TextBox

I am currently working with appending text to textboxes. In a winform I have two checkboxes and one textbox. Every time a check box is checked a text appears inside the textbox. But I am having difficulties taking out the text when the checkbox is unchecked. How can append text when checkbox is checked and take out text when unchecked?
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
ck = sender as CheckBox;
if (ck != null && ck.Checked)
{
textBox1.AppendText(" Example1 ");
}
else
{
textBox1.AppendText(" ");
}
}
private void checkBox2_CheckedChanged(object sender, EventArgs e)
{
ck = sender as CheckBox;
if (ck != null && ck.Checked)
{
textBox1.AppendText(" Example2 ");
}
else
{
textBox1.AppendText(" ");
}
}
Assuming you want to display :
Example 1 when the first checkbox is checked
Example 2 when the second is checked
Example 1 and Example 2 if both are checked
Empty if both are unchecked
The best is to centralize the UI logic in a single method that reflect your rules:
The approach is different as removing text I dont need. I start from an empty list and I fill it regarding the checkboxes are checked or not. Then I display it. By this way, I dont have to cope with trailing separators.
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
UpdateTextBox();
}
private void checkBox2_CheckedChanged(object sender, EventArgs e)
{
UpdateTextBox();
}
void UpdateTextBox()
{
var words = new List<string>();
if (checkbox1.Checked)
words.Add("Example 1");
if (checkbox2.Checked)
words.Add("Example 2");
textBox1.Text = string.Join(" ", words);
}
To take out just the text you added, you can use String.Replace:
textBox1.Text = textBox1.Text.Replace(" Example1 ", "");
Note that if the user changes the value, this text may or may not still be in the TextBox. I assume you are aware of this or this is simply an exercise.
if (ck != null && ck.Checked)
textBox1.Text = "Example";
else
textBox1.Text = "";
Do you mean
textBox1.Text = string.Empty
Or am I missing something ?
Try this
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
ck = sender as CheckBox;
if (ck != null && ck.Checked)
{
textBox1.AppendText(" Example1 ");
}
else
{
textBox1.Text = textBox1.Text.Replace(" Example1 ", "");
}
}
private void checkBox2_CheckedChanged(object sender, EventArgs e)
{
ck = sender as CheckBox;
if (ck != null && ck.Checked)
{
textBox1.AppendText(" Example2 ");
}
else
{
textBox1.Text = textBox1.Text.Replace(" Example2 ", "");
}
}

How to stop the first character in a text box from being '.'?

This is the code I currently have:
private void textBox_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = !char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar) && e.KeyChar != '.';
if (e.KeyChar == '.' && (sender as TextBox).Text.IndexOf('.') > -1) e.Handled = true;
}
KeyPress isn't good enough to do this kind of validation. A simple way to bypass it is to paste text into the text box with Ctrl+V. Or the context menu, no key event at all.
In this specific case, the TextChanged event will get the job done:
private void textBox_TextChanged(object sender, EventArgs e) {
var box = (TextBox)sender;
if (box.Text.StartsWith(".")) box.Text = "";
}
But there's a lot more to validating numeric values. You also need to reject stuff like 1.1.1 or 1.-2 etcetera. Use the Validating event instead. Drop an ErrorProvider on the form and implement the event like this:
private void textBox_Validating(object sender, CancelEventArgs e) {
var box = (TextBox)sender;
decimal value;
if (decimal.TryParse(box.Text, out value)) errorProvider1.SetError(box, "");
else {
e.Cancel = true;
box.SelectAll();
errorProvider1.SetError(box, "Invalid number");
}
}
You probably want to use the TextChanged event, since the user could paste in values. For the best experience given the requirements, I'd suggest simply removing any leading . characters.
void textBox1_TextChanged(object sender, EventArgs e)
{
if (textBox1.Text.StartsWith("."))
{
textBox1.Text = new string(textBox1.Text.SkipWhile(c => c == '.').ToArray());
}
}
This does not address a requirement to use only digits -- wasn't clear in the question if that is the case.
This works for copy and pasting too.
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
int decimalCount=0;
string rebuildText="";
for(int i=0; i<textBox1.Text.Length; i++)
{
if (textBox1.Text[i] == '.')
{
if (i == 0) break;
if (decimalCount == 0)
rebuildText += textBox1.Text[i];
decimalCount++;
}
else if ("0123456789".Contains(textBox1.Text[i]))
rebuildText += textBox1.Text[i];
}
textBox1.Text = rebuildText;
textBox1.SelectionStart = textBox1.Text.Length;
}
You can try this:
private void TextBox_TextChanged(object sender, EventArgs e)
{
TextBox.Text = TextBox.Text.TrimStart('.');
}

Categories